Page Builder by SiteOrigin - Version 2.6.3

Version Description

  • 6 March 2018 =
  • Use delete_post_meta_by_key instead of direct DB query to clear old cache renders.
  • Removed special handling for retrieving data from TinyMCE editor fields. Just use the field value directly.
  • Show correct preview for current editor when another editor has created an autosave.
  • Use minified CSS files.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 Page Builder by SiteOrigin
Version 2.6.3
Comparing to
See all releases

Code changes from version 2.6.2 to 2.6.3

css/admin.css CHANGED
@@ -1461,6 +1461,8 @@
1461
  padding: 6px;
1462
  }
1463
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper {
 
 
1464
  height: 100%;
1465
  box-sizing: border-box;
1466
  padding: 15px 10px;
@@ -1475,10 +1477,8 @@
1475
  margin: 0 0 13px 0;
1476
  }
1477
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot {
1478
- height: calc(100% - 50px);
1479
- background: #ffffff;
1480
  margin-bottom: 10px;
1481
- border: 1px solid #d0d0d0;
1482
  cursor: pointer;
1483
  }
1484
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading {
@@ -1500,14 +1500,21 @@
1500
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper {
1501
  display: block;
1502
  min-height: 40px;
 
 
1503
  }
1504
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description {
 
1505
  font-size: 0.9em;
1506
  color: #666;
1507
  margin-bottom: 10px;
 
 
1508
  }
1509
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom {
 
1510
  position: relative;
 
1511
  margin: 10px -10px -15px -10px;
1512
  background: #fcfcfc;
1513
  border-top: 1px solid #d0d0d0;
@@ -1516,6 +1523,8 @@
1516
  margin: 0;
1517
  padding: 16px 10px;
1518
  cursor: pointer;
 
 
1519
  }
1520
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons {
1521
  position: absolute;
1461
  padding: 6px;
1462
  }
1463
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper {
1464
+ display: flex;
1465
+ flex-flow: column nowrap;
1466
  height: 100%;
1467
  box-sizing: border-box;
1468
  padding: 15px 10px;
1477
  margin: 0 0 13px 0;
1478
  }
1479
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot {
1480
+ flex: 3 auto;
 
1481
  margin-bottom: 10px;
 
1482
  cursor: pointer;
1483
  }
1484
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading {
1500
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper {
1501
  display: block;
1502
  min-height: 40px;
1503
+ background: #808080;
1504
+ border: 1px solid #d0d0d0;
1505
  }
1506
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description {
1507
+ flex: 1 auto;
1508
  font-size: 0.9em;
1509
  color: #666;
1510
  margin-bottom: 10px;
1511
+ max-height: 60px;
1512
+ overflow: hidden;
1513
  }
1514
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom {
1515
+ flex: 1 auto;
1516
  position: relative;
1517
+ max-height: 50px;
1518
  margin: 10px -10px -15px -10px;
1519
  background: #fcfcfc;
1520
  border-top: 1px solid #d0d0d0;
1523
  margin: 0;
1524
  padding: 16px 10px;
1525
  cursor: pointer;
1526
+ overflow: hidden;
1527
+ white-space: nowrap;
1528
  }
1529
  .so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons {
1530
  position: absolute;
css/admin.min.css ADDED
@@ -0,0 +1 @@
 
1
+ @font-face{font-family:siteorigin-panels-icons;src:url(icons/panels-icons.eot);src:url(icons/panels-icons.eot) format("embedded-opentype"),url(icons/panels-icons.woff) format("woff"),url(icons/panels-icons.ttf) format("truetype"),url(icons/panels-icons.svg) format("svg");font-weight:400;font-style:normal}#so-panels-panels.attached-to-editor{margin-top:20px}#so-panels-panels.attached-to-editor .handlediv,#so-panels-panels.attached-to-editor .hndle{display:none!important}#so-panels-panels.attached-to-editor .inside{margin:0!important;padding:0!important}#so-panels-panels.attached-to-editor .so-toolbar .so-switch-to-standard{display:block}.siteorigin-panels-builder{position:relative}.siteorigin-panels-builder .so-tool-button{padding:6px 7px;text-decoration:none;line-height:1em;float:left;margin-right:2px;display:block;visibility:visible;position:relative;cursor:pointer;border:1px solid #bebebe;background:#eee;background:-o-linear-gradient(#f9f9f9,#eee);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#f9f9f9",endColorstr="#eeeeee",GradientType=0);box-shadow:0 1px 1px rgba(0,0,0,.04),inset 0 1px 0 hsla(0,0%,100%,.5);outline:none;border-radius:2px}.siteorigin-panels-builder .so-tool-button .so-panels-icon{font-size:12px}.siteorigin-panels-builder .so-tool-button span{display:inline-block;color:#666;text-shadow:0 1px 0 #fff;min-width:10px;text-align:center}.siteorigin-panels-builder .so-tool-button:hover{background:#fff}.siteorigin-panels-builder .so-tool-button:hover span{color:#444}.siteorigin-panels-builder .so-builder-toolbar{-ms-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #d0d0d0;background:#f5f5f5;line-height:1em;z-index:101;white-space:nowrap;overflow-x:hidden;position:relative;box-shadow:0 1px 1px rgba(0,0,0,.04);top:0;left:0;width:100%;padding:6px 9px;margin-top:0!important;zoom:1}.siteorigin-panels-builder .so-builder-toolbar:before{content:"";display:block}.siteorigin-panels-builder .so-builder-toolbar:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button{display:inline-block;color:#666;padding:2px 10px 2px 8px}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button .so-button-text{margin:3px 0 2px;font-size:11px}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button .so-panels-icon{float:left;margin:3px 7px 2px 0;font-size:14px;color:#747474}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button:hover,.siteorigin-panels-builder .so-builder-toolbar .so-tool-button:hover .so-panels-icon{color:#444}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button.so-learn{background:#e5e5e5;background:-o-linear-gradient(#f6f6f6,#e5e5e5);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#f6f6f6",endColorstr="#e5e5e5",GradientType=0)}.siteorigin-panels-builder .so-builder-toolbar .so-tool-button.so-learn:hover{background:#fff}.siteorigin-panels-builder .so-builder-toolbar .so-switch-to-standard{cursor:pointer;float:right;display:none;text-decoration:none;color:#666;padding:5px 6px;border-radius:2px;border:1px solid transparent;font-size:11px}.siteorigin-panels-builder .so-builder-toolbar .so-switch-to-standard:hover{background:#fafafa;border:1px solid #999;color:#444}.siteorigin-panels-builder .so-rows-container{padding:20px 15px 0}.siteorigin-panels-builder .so-rows-container .so-row-color-1.so-row-color{background-color:#cde2ec;border:1px solid #a4cadd}.siteorigin-panels-builder .so-rows-container .so-row-color-1.so-row-color.so-row-color-selected:before{background:#a8cdde}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .cell-wrapper{background-color:#cde2ec}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell.cell-selected .cell-wrapper{background-color:#99c4d8}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .resize-handle{background-color:#e7f1f6}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-1 .so-cells .cell .resize-handle:hover{background-color:#dcebf2}.siteorigin-panels-builder .so-rows-container .so-row-color-2.so-row-color{background-color:#f2c2be;border:1px solid #e9968f}.siteorigin-panels-builder .so-rows-container .so-row-color-2.so-row-color.so-row-color-selected:before{background:#ea9a93}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .cell-wrapper{background-color:#f2c2be}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell.cell-selected .cell-wrapper{background-color:#e68a83}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .resize-handle{background-color:#f8dedc}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-2 .so-cells .cell .resize-handle:hover{background-color:#f5d2cf}.siteorigin-panels-builder .so-rows-container .so-row-color-3.so-row-color{background-color:#d5ccdf;border:1px solid #b9aac9}.siteorigin-panels-builder .so-rows-container .so-row-color-3.so-row-color.so-row-color-selected:before{background:#bbadcb}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .cell-wrapper{background-color:#d5ccdf}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell.cell-selected .cell-wrapper{background-color:#b1a0c3}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .resize-handle{background-color:#e7e2ed}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-3 .so-cells .cell .resize-handle:hover{background-color:#dfd9e7}.siteorigin-panels-builder .so-rows-container .so-row-color-4.so-row-color{background-color:#cae7cd;border:1px solid #a3d6a9}.siteorigin-panels-builder .so-rows-container .so-row-color-4.so-row-color.so-row-color-selected:before{background:#a7d7ac}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .cell-wrapper{background-color:#cae7cd}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell.cell-selected .cell-wrapper{background-color:#99d19f}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .resize-handle{background-color:#e3f2e4}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-4 .so-cells .cell .resize-handle:hover{background-color:#d8edda}.siteorigin-panels-builder .so-rows-container .so-row-color-5.so-row-color{background-color:#e2dcb1;border:1px solid #d3ca88}.siteorigin-panels-builder .so-rows-container .so-row-color-5.so-row-color.so-row-color-selected:before{background:#d4cb8c}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .cell-wrapper{background-color:#e2dcb1}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell.cell-selected .cell-wrapper{background-color:#cfc57d}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .resize-handle{background-color:#ece8cb}.siteorigin-panels-builder .so-rows-container .so-row-container.so-row-color-5 .so-cells .cell .resize-handle:hover{background-color:#e8e3c0}.siteorigin-panels-builder .so-rows-container h3.so-row-label{display:inline-block;font-size:1em;font-weight:500;color:#474747;margin:0 0 0 4px;line-height:22px;float:left}.siteorigin-panels-builder .so-rows-container .so-row-toolbar{zoom:1;margin-bottom:4px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar:before{content:"";display:block}.siteorigin-panels-builder .so-rows-container .so-row-toolbar:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button{-ms-box-sizing:border-box;box-sizing:border-box;padding:4px;float:right}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button .so-panels-icon{color:#777;font-size:11px;width:11px;height:11px;display:block}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button:hover .so-panels-icon{color:#555}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-tool-button.so-row-move{cursor:move}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper{visibility:hidden;opacity:0;transition:visibility 0s linear 75ms,opacity 75ms linear;z-index:101;right:-10px;top:100%;width:125px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li a.so-row-delete{color:#a00}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li a.so-row-delete:hover{color:#fff;background:#a00}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container{display:flex;justify-content:space-around;padding:5px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container .so-row-color{display:inline-block;cursor:pointer;position:relative;text-align:center;width:14px;height:14px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper .so-dropdown-links-wrapper ul li.so-row-colors-container .so-row-color.so-row-color-selected:before{content:"";display:block;position:absolute;top:2px;bottom:2px;left:2px;right:2px}.siteorigin-panels-builder .so-rows-container .so-row-toolbar .so-dropdown-wrapper:hover .so-dropdown-links-wrapper{visibility:visible;opacity:1;transition-delay:0s}.siteorigin-panels-builder .so-rows-container .ui-sortable-placeholder{visibility:visible!important;background:#f7f7f7;-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container{margin-bottom:15px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.siteorigin-panels-builder .so-rows-container .so-row-container.ui-sortable-helper{opacity:.9}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells{zoom:1;margin:0 -5px;position:relative}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells:before{content:"";display:block}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells:after{content:"";display:table;clear:both}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .ui-resizable-handle.ui-resizable-w{width:10px;left:-11px;cursor:col-resize;background:rgba(0,150,211,.25);transition:background .25s ease-in-out}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .ui-resizable-handle.ui-resizable-w:hover{background:rgba(0,150,211,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell{-ms-box-sizing:border-box;box-sizing:border-box;float:left;position:relative;padding:0 5px}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.so-first{margin-left:0}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.so-last{margin-right:0}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .cell-wrapper{background:#e4eff4;padding:7px 7px 0;height:100%;min-height:63px;transition:background .25s ease-in-out 0s}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell.cell-selected .cell-wrapper{background-size:3px 3px}}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .cell-wrapper{-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget{cursor:move;margin-bottom:7px;background:#f9f9fb;border:1px solid hsla(0,0%,100%,.75);max-height:49px;box-shadow:0 1px 1px rgba(0,0,0,.075);-ms-box-sizing:border-box;box-sizing:border-box}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-no-move{cursor:auto}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget:hover{border:1px solid hsla(0,0%,100%,.55);background:#fff;box-shadow:0 0 2px rgba(0,0,0,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .so-widget-wrapper{padding:7px 8px;overflow:hidden;position:relative}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget h4{display:block;cursor:pointer;margin:0 15px 3px 0;font-weight:600;line-height:1.25em;color:#474747;text-shadow:0 1px 0 #fff;white-space:nowrap}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget h4 span{font-weight:400;display:inline-block;color:#999;text-shadow:0 1px 0 #fff;margin-left:12px;margin-right:5px;font-style:italic}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-no-edit h4{cursor:auto}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions{font-size:12px;position:absolute;top:5px;right:7px;cursor:pointer;padding:2px 2px 2px 15px;z-index:10}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions:hover{background:#feffff}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions:hover a{opacity:1}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a{display:none;margin-right:3px;text-decoration:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a.widget-delete{color:red}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .title .actions a.widget-delete:hover{color:#fff;background:red}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget:hover .title a{display:inline-block;opacity:.5}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.panel-being-dragged .title .actions{display:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget small{display:block;height:16px;overflow:hidden;color:#777}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget .form{display:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover{background:#f5f5f5;border:1px solid #a6bac1;box-shadow:none}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only:hover small,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-widget-read-only small{opacity:.5}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered{background:#3a7096;border:1px solid #39618c;box-shadow:0 2px 2px rgba(0,0,0,.1)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered h4,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered small,.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered span{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.85)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget.so-hovered small{color:#eee}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .widgets-container .so-widget-sortable-highlight{border:1px solid rgba(0,0,0,.075);background:rgba(0,0,0,.025);-ms-box-sizing:border-box;box-sizing:border-box;height:49px;margin-bottom:7px;position:relative;box-shadow:inset 2px 2px 2px rgba(0,0,0,.01)}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell .resize-handle{z-index:100;position:absolute;top:0;width:10px;left:-5px;cursor:col-resize;background:#f6fafb;height:100%;transition:background .25s ease-in-out 0s}.siteorigin-panels-builder .so-rows-container .so-row-container .so-cells .cell:first-child .resize-handle{display:none}.siteorigin-panels-builder .so-panels-welcome-message{text-align:center;padding:0 15px 20px;color:#555;line-height:1.8em}.siteorigin-panels-builder .so-panels-welcome-message .so-message-wrapper{padding:15px 10px;background:#f8f8f8;border:1px solid #e0e0e0}.siteorigin-panels-builder .so-panels-welcome-message .so-tool-button{font-size:inherit;display:inline-block;float:none;color:#666;padding:5px 10px;margin:0 3px}.siteorigin-panels-builder .so-panels-welcome-message .so-tool-button .so-panels-icon{color:#777;font-size:.8em}.siteorigin-panels-builder .so-panels-welcome-message .so-tip-wrapper{margin-top:15px;font-size:.95em}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar{padding:10px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button{padding-right:2px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button .so-panels-icon{font-size:14px}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button.so-learn,.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar>.so-tool-button span.so-button-text{display:none}.siteorigin-panels-builder.so-display-narrow .so-builder-toolbar .so-switch-to-standard,.siteorigin-panels-builder.so-display-narrow .widgets-container .so-widget .actions{display:none!important}.so-widget.ui-sortable-helper.widget-being-dragged{z-index:500002!important;opacity:.9;pointer-events:none;border:1px solid rgba(0,0,0,.35)!important;cursor:move;margin-bottom:7px;background:#f9f9fb;border:1px solid hsla(0,0%,100%,.75);max-height:49px;box-shadow:0 1px 1px rgba(0,0,0,.075);-ms-box-sizing:border-box;box-sizing:border-box}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-no-move{cursor:auto}.so-widget.ui-sortable-helper.widget-being-dragged:hover{border:1px solid hsla(0,0%,100%,.55);background:#fff;box-shadow:0 0 2px rgba(0,0,0,.1)}.so-widget.ui-sortable-helper.widget-being-dragged .so-widget-wrapper{padding:7px 8px;overflow:hidden;position:relative}.so-widget.ui-sortable-helper.widget-being-dragged h4{display:block;cursor:pointer;margin:0 15px 3px 0;font-weight:600;line-height:1.25em;color:#474747;text-shadow:0 1px 0 #fff;white-space:nowrap}.so-widget.ui-sortable-helper.widget-being-dragged h4 span{font-weight:400;display:inline-block;color:#999;text-shadow:0 1px 0 #fff;margin-left:12px;margin-right:5px;font-style:italic}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-no-edit h4{cursor:auto}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions{font-size:12px;position:absolute;top:5px;right:7px;cursor:pointer;padding:2px 2px 2px 15px;z-index:10}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions:hover{background:#feffff}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions:hover a{opacity:1}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a{display:none;margin-right:3px;text-decoration:none}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a.widget-delete{color:red}.so-widget.ui-sortable-helper.widget-being-dragged .title .actions a.widget-delete:hover{color:#fff;background:red}.so-widget.ui-sortable-helper.widget-being-dragged:hover .title a{display:inline-block;opacity:.5}.so-widget.ui-sortable-helper.widget-being-dragged.panel-being-dragged .title .actions{display:none}.so-widget.ui-sortable-helper.widget-being-dragged small{display:block;height:16px;overflow:hidden;color:#777}.so-widget.ui-sortable-helper.widget-being-dragged .form{display:none}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover{background:#f5f5f5;border:1px solid #a6bac1;box-shadow:none}.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only:hover small,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-widget-read-only small{opacity:.5}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered{background:#3a7096;border:1px solid #39618c;box-shadow:0 2px 2px rgba(0,0,0,.1)}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered h4,.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered small,.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered span{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.85)}.so-widget.ui-sortable-helper.widget-being-dragged.so-hovered small{color:#eee}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-builder-container{padding-top:0}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-rows-container{padding:10px 0 0}.widgets-holder-wrap .widget-inside .siteorigin-panels-builder .so-builder-toolbar{padding-left:15px;padding-right:15px;margin:0 -15px}.so-panels-dialog .so-content,.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-overlay,.so-panels-dialog .so-right-sidebar,.so-panels-dialog .so-title-bar,.so-panels-dialog .so-toolbar{z-index:100001;position:fixed;-ms-box-sizing:border-box;box-sizing:border-box;padding:15px}.so-panels-dialog .so-content,.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-right-sidebar{overflow-y:auto}.so-panels-dialog .so-overlay{top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5)}.so-panels-dialog .so-content{top:80px;left:30px;right:30px;bottom:88px;background-color:#fdfdfd;overflow-x:hidden;box-shadow:inset 0 2px 2px rgba(0,0,0,.03)}.so-panels-dialog .so-content>:first-child{margin-top:0}.so-panels-dialog .so-content>:last-child{margin-bottom:0}.so-panels-dialog .so-content .so-content-tabs>*{display:none}.so-panels-dialog .so-title-bar{left:30px;right:30px;top:30px;height:50px;background-color:#fafafa;border-bottom:1px solid #d8d8d8}.so-panels-dialog .so-title-bar h3.so-title{-ms-box-sizing:border-box;box-sizing:border-box;margin:-3px 150px 0 -3px;padding:5px 6px;display:block}.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:focus,.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:hover{outline:none;background-color:#f0f0f0}.so-panels-dialog .so-title-bar h3.so-title.so-title-editable:focus{margin-top:-4px;margin-left:-4px;border:1px solid #e4e4e4}.so-panels-dialog .so-title-bar input[type=text].so-edit-title{margin-top:-3px;margin-left:-3px;display:none;color:#23282d;font-size:1.3em;font-weight:600;border:none;box-shadow:none;background-color:#f0f0f0;padding:4px 5px}.so-panels-dialog .so-title-bar h3.so-parent-link{cursor:pointer;position:relative;float:left;margin:0 15px 0 0!important;padding:0 27px 0 0!important}.so-panels-dialog .so-title-bar h3.so-parent-link .so-separator{position:absolute;top:-15px;right:0;width:12px;height:50px;display:block;background:url(images/dialog-separator.png) no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-dialog .so-title-bar h3.so-parent-link .so-separator{background:url(images/dialog-separator@2x.png) no-repeat;background-size:cover}}.so-panels-dialog .so-title-bar a{cursor:pointer;position:absolute;box-sizing:border-box;width:50px;height:50px;display:block;top:0;right:0;transition:all .2s ease 0s;background:#fafafa;border-left:1px solid #d8d8d8;border-bottom:1px solid #d8d8d8}.so-panels-dialog .so-title-bar a:hover{background:#e9e9e9}.so-panels-dialog .so-title-bar a:hover .so-dialog-icon{color:#333}.so-panels-dialog .so-title-bar a .so-dialog-icon{position:absolute;top:50%;left:50%;text-decoration:none;width:20px;height:20px;margin-left:-10px;margin-top:-10px;color:#666;text-align:center}.so-panels-dialog .so-title-bar a .so-dialog-icon:before{font:400 20px/1em dashicons;top:7px;left:13px}.so-panels-dialog .so-title-bar a.so-close{right:0}.so-panels-dialog .so-title-bar a.so-close .so-dialog-icon:before{content:"\f335"}.so-panels-dialog .so-title-bar a.so-next{right:50px}.so-panels-dialog .so-title-bar a.so-next .so-dialog-icon:before{content:"\f345"}.so-panels-dialog .so-title-bar a.so-previous{right:100px}.so-panels-dialog .so-title-bar a.so-previous .so-dialog-icon:before{content:"\f341"}.so-panels-dialog .so-title-bar a.so-nav.so-disabled{cursor:default;pointer-events:none}.so-panels-dialog .so-title-bar a.so-nav.so-disabled .so-dialog-icon{color:#ddd}.so-panels-dialog .so-title-bar.so-has-icon{padding-left:45px}.so-panels-dialog .so-title-bar.so-has-icon .so-panels-icon{position:absolute;top:14.5px;left:14px;font-size:22px;line-height:22px;display:block;width:22px;height:22px;text-align:center;color:#666}.so-panels-dialog .so-toolbar{left:30px;right:30px;bottom:30px;height:58px;background-color:#fafafa;border-top:1px solid #d8d8d8;z-index:100002}.so-panels-dialog .so-toolbar .so-status{float:left;padding-top:6px;padding-bottom:6px;font-style:italic;color:#999;line-height:1em}.so-panels-dialog .so-toolbar .so-status.so-panels-loading{padding-left:26px;background-position:0}.so-panels-dialog .so-toolbar .so-status .dashicons-warning{color:#a00;vertical-align:middle;margin-right:7px;margin-top:-1px}.so-panels-dialog .so-toolbar .so-buttons{float:right}.so-panels-dialog .so-toolbar .so-buttons .action-buttons{position:absolute;left:15px;top:50%;margin-top:-.65em}.so-panels-dialog .so-toolbar .so-buttons .action-buttons a{cursor:pointer;display:inline;padding:.2em .5em;line-height:1em;margin-right:.5em;text-decoration:none}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-delete{color:#a00}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-delete:hover{background:#a00;color:#fff}.so-panels-dialog .so-toolbar .so-buttons .action-buttons .so-duplicate:hover{text-decoration:underline}.so-panels-dialog .so-left-sidebar,.so-panels-dialog .so-right-sidebar{background-color:#f3f3f3}.so-panels-dialog .so-left-sidebar{display:none;top:30px;left:30px;bottom:30px;width:290px;border-right:1px solid #d8d8d8}.so-panels-dialog .so-left-sidebar h4{margin:0 0 20px;font-size:18px}.so-panels-dialog .so-left-sidebar .so-sidebar-search{width:100%;padding:6px;margin-bottom:20px}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs{list-style:none;margin:0 -15px}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li{margin-bottom:0}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li a{padding:7px 16px;display:block;font-size:14px;text-decoration:none;box-shadow:none!important}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li a:hover{background:#fff}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li.tab-active a{color:#555;font-weight:700;background:#fff}.so-panels-dialog .so-left-sidebar .so-sidebar-tabs li.tab-active a:hover{background:#fff}.so-panels-dialog .so-right-sidebar{display:none;top:80px;right:30px;bottom:88px;width:290px;border-left:1px solid #d8d8d8}.so-panels-dialog .so-right-sidebar h3{color:#333}.so-panels-dialog .so-right-sidebar h3:first-child{margin-top:0}.so-panels-dialog .so-sidebar .form-field{margin-bottom:20px}.so-panels-dialog .so-sidebar .form-field label{font-weight:500;font-size:15px;display:block;margin-bottom:10px}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-content,.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-title-bar,.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-toolbar{left:320px}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-content{box-shadow:inset 2px 2px 2px rgba(0,0,0,.03)}.so-panels-dialog.so-panels-dialog-has-left-sidebar .so-left-sidebar{display:block}.so-panels-dialog.so-panels-dialog-has-right-sidebar .so-content{right:320px}.so-panels-dialog.so-panels-dialog-has-right-sidebar .so-right-sidebar{display:block}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget{border-radius:2px;border:1px solid #ccc;cursor:pointer;padding:10px;background:#f9f9f9;box-shadow:0 1px 2px rgba(0,0,0,.075),inset 0 1px 0 #fff;margin-bottom:15px}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget:hover{border:1px solid #bbb;background:#fff}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current{border-color:#0074a2;background:#2ea2cc;cursor:auto;box-shadow:0 1px 2px rgba(0,0,0,.15),inset 0 1px 0 hsla(0,0%,100%,.2)}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current h3{color:#fff}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current small{color:#eee}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget.so-current:hover{border-color:#0074a2;background:#2ea2cc}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget:last-child{margin-bottom:0}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget h3{margin:0 0 7px;padding:0;height:1.2em;color:#222;font-size:14px}.so-panels-dialog.so-panels-dialog-edit-widget .so-left-sidebar .so-widgets .so-widget small{font-size:11px;line-height:1.25em;display:block;overflow:hidden;color:#888}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list{zoom:1;margin:0 -5px -10px;min-height:10px}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list:before{content:"";display:block}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list:after{content:"";display:table;clear:both}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{-ms-user-select:none;-moz-user-select:-moz-none;-webkit-user-select:none;user-select:none;-ms-box-sizing:border-box;box-sizing:border-box;width:25%;padding:0 5px;margin-bottom:10px;float:left}@media (max-width:1280px){.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{width:33.333%}}@media (max-width:960px){.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type{width:50%}}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type h3{margin:0 0 7px;padding:0;color:#222;font-size:14px}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type small{font-size:11px;min-height:2.5em;line-height:1.25em;display:block;overflow:hidden;color:#888}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type .widget-icon{font-size:20px;width:20px;height:20px;color:#666;float:left;margin:-1px .5em 0 0}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type-wrapper{border:1px solid #ccc;cursor:pointer;padding:10px;background:#f8f8f8;box-shadow:0 1px 2px rgba(0,0,0,.075)}.so-panels-dialog.so-panels-dialog-add-widget .widget-type-list .widget-type-wrapper:hover{border:1px solid #bbb;background:#fff;box-shadow:0 2px 2px rgba(0,0,0,.075)}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form{zoom:1;padding:8px;border:1px solid #ccc;margin-bottom:20px;background:#f3f3f3}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form:before{content:"";display:block}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form:after{content:"";display:table;clear:both}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form button,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form input,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form select,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form span,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form strong{display:inline;margin:1px 5px;outline:none;box-shadow:none}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form button{margin-top:2px}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-set-form label{display:inline}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview{margin:0 -6px;height:360px;position:relative;white-space:nowrap}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell-in,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell-weight{-ms-box-sizing:border-box;box-sizing:border-box}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell{display:inline-block;position:relative;padding:0 6px;cursor:pointer}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in{border:1px solid #bcccd2;min-height:360px;background:#e4eff4;position:relative}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in.cell-selected{background:#cae7f4 url(images/cell-selected.png) repeat;border-color:#9abcc7;box-shadow:0 0 5px rgba(0,0,0,.2)}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input{position:absolute;font-size:17px;font-weight:700;top:50%;left:50%;width:80px;text-align:center;color:#5e6d72;margin:-.95em 0 0 -40px;padding:10px 0;border:1px solid transparent;line-height:1.4em!important;overflow:hidden;cursor:pointer}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input:after,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight:after{content:"%"}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input:hover,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight:hover{background:#f6f6f6;border:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .preview-cell-in .preview-cell-weight-input{background:#f6f6f6;border:1px solid #d0d0d0;box-shadow:none}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle{z-index:100;position:absolute;top:0;width:12px;left:-6px;cursor:col-resize;background:#e5f4fb;height:360px;transition:background .15s ease-in-out 0s}.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle.ui-draggable-dragging,.so-panels-dialog.so-panels-dialog-row-edit .so-content .row-preview .preview-cell .resize-handle:hover{background:#b7e0f1}.so-panels-dialog.so-panels-dialog-history .so-left-sidebar{padding:0}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry{padding:10px;background:#f8f8f8;cursor:pointer;border-bottom:1px solid #ccc}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry h3{margin:0 0 .6em;font-size:12px;font-weight:700;color:#444;line-height:1em}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry .timesince{color:#999;font-size:11px;line-height:1em}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry:hover{background:#f0f0f0}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry.so-selected{background:#eee}.so-panels-dialog.so-panels-dialog-history .history-entries .history-entry .count{color:#999}.so-panels-dialog.so-panels-dialog-history .so-content{padding:0;overflow-y:hidden}.so-panels-dialog.so-panels-dialog-history .so-content form.history-form{display:none}.so-panels-dialog.so-panels-dialog-history .so-content iframe.siteorigin-panels-history-iframe{width:100%;height:100%}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content{padding-left:10px;padding-right:10px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-error-message{font-size:14px;border:1px solid #ccc;background:#f8f8f8;padding:15px 20px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .export-file-ui{padding:5px 15px;text-align:right}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui{padding:15px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-drop-message{display:none}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui.has-drag-drop .drag-drop-message{display:block}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui p.drag-drop-message{font-size:1em;margin-bottom:0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-upload-area{display:block;-ms-box-sizing:border-box;box-sizing:border-box;padding:50px 30px;border:4px dashed #e0e0e0;text-align:center;transition:all .25s ease 0s}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .drag-upload-area.file-dragover{background-color:#f2f9fc;border-color:#0074a2}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .progress-bar{display:none;padding:2px;border:2px solid #2181b1;border-radius:2px;margin-top:20px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .progress-bar .progress-percent{height:14px;background-color:#358ebe;border-radius:1px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .import-upload-ui .file-browse-button{padding:12px 30px;height:auto}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-browse{background:#f3f3f3;border-bottom:1px solid #d0d0d0;margin:-15px -10px 15px;padding:15px;font-weight:700}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items-wrapper{display:flex;flex-flow:row wrap}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-no-results{margin:20px 0;padding:0 5px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{-ms-box-sizing:border-box;box-sizing:border-box;padding:6px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-directory-item-wrapper{display:flex;flex-flow:column nowrap;height:100%;box-sizing:border-box;padding:15px 10px;background:#f7f7f7;border:1px solid #d0d0d0;box-shadow:0 1px 1px rgba(0,0,0,.1)}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-title{font-size:15px;margin:0 0 13px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot{flex:3 auto;margin-bottom:10px;cursor:pointer}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading{background-image:url(images/wpspin_light.gif);background-position:50%;background-repeat:no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot.so-loading{background-image:url(images/wpspin_light-2x.gif);background-size:16px 16px}}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot img{display:block;width:100%;height:auto}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-screenshot .so-screenshot-wrapper{display:block;min-height:40px;background:gray;border:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-description{flex:1 auto;font-size:.9em;color:#666;margin-bottom:10px;max-height:60px;overflow:hidden}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom{flex:1 auto;position:relative;max-height:50px;margin:10px -10px -15px;background:#fcfcfc;border-top:1px solid #d0d0d0}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-title{margin:0;padding:16px 10px;cursor:pointer;overflow:hidden;white-space:nowrap}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item .so-bottom .so-buttons{position:absolute;z-index:2;top:0;bottom:0;right:0;height:100%;visibility:hidden;-ms-box-sizing:border-box;box-sizing:border-box;padding:11px 10px 10px 15px;border-left:1px solid #d0d0d0;background:#f6f6f6;box-shadow:-1px 0 1px rgba(0,0,0,.05)}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item:hover .so-buttons{visibility:visible}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected{background-color:#e5f4fa}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-directory-item-wrapper{background:#deeef4;border-color:#9abcc7}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom{background:#f8fdff;border-color:#bcccd2}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom .so-title{color:#3e484c}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item.selected .so-bottom .so-buttons{background:#eaf2f6;border-color:#bcccd2}@media only screen and (min-width:1680px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:20%}}@media only screen and (max-width:1679px) and (min-width:1280px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:25%}}@media only screen and (max-width:1279px) and (min-width:1140px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:33.333%}}@media only screen and (max-width:1139px){.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-items .so-directory-item{width:50%}}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-pages{margin-top:15px;padding:0 5px}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-content .so-directory-pages .button-disabled{pointer-events:none}.so-panels-dialog.so-panels-dialog-prebuilt-layouts .so-toolbar .so-buttons select.so-layout-position{vertical-align:baseline}.so-panels-dialog .so-visual-styles{margin:-15px}.so-panels-dialog .so-visual-styles h3{line-height:1em;margin:0;padding:20px 15px;border-bottom:1px solid #ddd}.so-panels-dialog .so-visual-styles .style-section-head{background:#fff;padding:15px 10px;border-bottom:1px solid #ddd;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.so-panels-dialog .so-visual-styles .style-section-head h4{margin:0}.so-panels-dialog .so-visual-styles .style-section-fields{padding:15px;border-bottom:1px solid #ddd;background:#f7f7f7}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper{margin-bottom:20px}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper:last-child{margin-bottom:0}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper>label{font-weight:700;display:block;margin-bottom:3px}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field{zoom:1}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field:before{content:"";display:block}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field:after{content:"";display:table;clear:both}.so-panels-dialog .so-visual-styles .style-section-fields .style-field-wrapper .style-field input{font-size:12px}.so-panels-dialog .so-visual-styles .style-input-wrapper{zoom:1}.so-panels-dialog .so-visual-styles .style-input-wrapper:before{content:"";display:block}.so-panels-dialog .so-visual-styles .style-input-wrapper:after{content:"";display:table;clear:both}.so-panels-dialog .so-visual-styles .style-input-wrapper input{max-width:100%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-inputs{overflow:auto;margin:0 -3px 4px}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper{box-sizing:border-box;float:left;width:25%;padding:0 3px}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value{border-width:1px;display:block;max-width:100%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-top{box-shadow:inset 0 2px 1px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-right{box-shadow:inset -3px 0 2px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-bottom{box-shadow:inset 0 -2px 1px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-wrapper .measurement-value.measurement-left{box-shadow:inset 3px 0 2px rgba(0,115,170,.35)}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-unit-multiple{width:100%;display:block}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-unit-single{float:right;width:25%}.so-panels-dialog .so-visual-styles .style-field-measurement .measurement-value-single{float:left;width:72%}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector{display:inline-block;background-color:#f7f7f7;border:1px solid #ccc;height:28px;float:left;border-radius:3px;cursor:pointer;box-shadow:inset 0 1px #fff}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector .current-image{height:28px;width:28px;float:left;background:#fff;border-right:1px solid #ccc;background-size:cover;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:0;-webkit-border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:0;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px;border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:3px;border-top-left-radius:3px;background-clip:padding-box}.so-panels-dialog .so-visual-styles .style-field-image .so-image-selector .select-image{font-size:12px;line-height:28px;float:left;padding:0 8px;color:#555}.so-panels-dialog .so-visual-styles .style-field-image .remove-image{font-size:12px;margin-top:4px;margin-left:15px;display:inline-block;float:left;color:#666;text-decoration:none}.so-panels-dialog .so-visual-styles .style-field-image .remove-image .remove-image{color:#333}.so-panels-dialog .so-visual-styles .style-field-checkbox label{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.so-panels-dialog .so-visual-styles .so-field-code{font-size:12px;font-family:Courier\ 10 Pitch,Courier,monospace}.so-panels-dialog .so-visual-styles .so-description{color:#999;font-size:12px;margin-top:5px;margin-bottom:0;font-style:italic;clear:both}.so-panels-dialog .so-visual-styles.so-cell-styles{margin-top:15px}.so-panels-dialog .so-content .siteorigin-panels-builder .so-builder-toolbar{border:1px solid #dedede}.so-panels-dialog .so-content .siteorigin-panels-builder .so-rows-container{padding:20px 0 0}.so-panels-dialog .so-content .siteorigin-panels-builder .so-panels-welcome-message{padding-left:0;padding-right:0}.so-panels-dialog .so-dropdown-wrapper input[type=button].button-primary{width:125px;height:28px}.so-panels-dialog .so-dropdown-wrapper .so-dropdown-links-wrapper{display:block;z-index:11;bottom:28px;width:125px}.so-panels-dialog .so-dropdown-wrapper .so-dropdown-links-wrapper.hidden{display:none}.wp-customizer .so-panels-dialog .so-content,.wp-customizer .so-panels-dialog .so-left-sidebar,.wp-customizer .so-panels-dialog .so-overlay,.wp-customizer .so-panels-dialog .so-right-sidebar,.wp-customizer .so-panels-dialog .so-title-bar,.wp-customizer .so-panels-dialog .so-toolbar{z-index:500001}.wp-customizer .so-panels-dialog .so-toolbar{z-index:500002}.so-panels-live-editor>div{position:fixed;z-index:99999;-ms-box-sizing:border-box;box-sizing:border-box}.so-panels-live-editor .live-editor-form{display:none}.so-panels-live-editor .live-editor-collapse{position:fixed;top:18px;left:10px;line-height:1em;cursor:pointer;z-index:100000}.so-panels-live-editor .live-editor-collapse .collapse-icon{float:left;margin:-4px 6px 0 0;border-radius:50%;width:20px;height:20px;overflow:hidden;transition:all .25s ease 0s}.so-panels-live-editor .live-editor-collapse .collapse-icon:before{display:block;content:"\f148";background:#eee;font:normal 20px/1 dashicons;speak:none;padding:0;-webkit-font-smoothing:antialiased}.so-panels-live-editor .live-editor-collapse:hover{color:#0073aa}.so-panels-live-editor .live-editor-collapse:hover .collapse-icon{box-shadow:0 0 3px rgba(30,140,190,.8)}.so-panels-live-editor .so-sidebar-tools{background:#eee;border-bottom:1px solid #ddd;border-right:1px solid #d0d0d0;top:0;left:0;height:46px;width:360px}.so-panels-live-editor .so-sidebar-tools .live-editor-close{margin:9px 10px 0 15px;float:right}.so-panels-live-editor .so-sidebar-tools .live-editor-mode{float:right;margin:9px 4px 0 0}.so-panels-live-editor .so-sidebar-tools .live-editor-mode .dashicons{font-size:30px;width:30px;height:30px;cursor:pointer;color:#999}.so-panels-live-editor .so-sidebar-tools .live-editor-mode .dashicons:hover{color:#666}.so-panels-live-editor .so-sidebar-tools .live-editor-mode.so-active .dashicons,.so-panels-live-editor .so-sidebar-tools .live-editor-mode.so-active .dashicons:hover{color:#0073aa}.so-panels-live-editor .so-sidebar{top:46px;left:0;bottom:0;width:360px;overflow-y:auto;background:#f7f7f7;border-right:1px solid #d0d0d0}.so-panels-live-editor .so-sidebar .siteorigin-panels-builder .so-rows-container{padding:10px 10px 0!important}.so-panels-live-editor .so-preview{top:0;right:0;bottom:0;left:360px;background-color:#191e23}.so-panels-live-editor .so-preview form{display:none}.so-panels-live-editor .so-preview iframe{float:left;width:100%;height:100%;margin:0 auto}.so-panels-live-editor .so-preview-overlay{display:none;opacity:.975;top:0;right:0;bottom:0;left:360px;background-color:#f4f4f4;cursor:wait}.so-panels-live-editor .so-preview-overlay .so-loading-container{opacity:.6;position:absolute;top:50%;width:200px;padding:2px;border-radius:5px;left:50%;margin-left:-104px;margin-top:-9px;border:2px solid #aaa}.so-panels-live-editor .so-preview-overlay .so-loading-container .so-loading-bar{width:50%;border-radius:3px;height:10px;background:#aaa}.so-panels-live-editor.so-collapsed .live-editor-collapse .collapse-icon{transform:rotate(180deg)}.so-panels-live-editor.so-collapsed .so-sidebar,.so-panels-live-editor.so-collapsed .so-sidebar-tools{display:none}.so-panels-live-editor.so-collapsed .so-preview,.so-panels-live-editor.so-collapsed .so-preview-overlay{left:0}.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{max-width:480px;max-height:640px;position:absolute;top:50%;left:50%;margin-left:-240px;margin-top:-320px}@media (max-width:840px){.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}@media (max-height:640px){.so-panels-live-editor.live-editor-mobile-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}.so-panels-live-editor.live-editor-tablet-mode .so-preview iframe{position:absolute;max-width:768px;top:0;left:50%;margin-left:-384px}@media (max-width:1128px){.so-panels-live-editor.live-editor-tablet-mode .so-preview iframe{position:static;margin-left:0;margin-top:0}}.so-panels-loading{background-image:url(images/wpspin_light.gif);background-position:50%;background-repeat:no-repeat}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.so-panels-loading{background-image:url(images/wpspin_light-2x.gif);background-size:16px 16px}}#panels-home-page .switch{margin:0 10px 0 0;float:left;position:relative;display:inline-block;vertical-align:top;width:68px;height:24px;padding:3px;background-color:#fff;border-radius:24px;box-shadow:inset 0 -1px #fff,inset 0 1px 1px rgba(0,0,0,.05);cursor:pointer;background-image:linear-gradient(180deg,#eee,#fff 25px)}#panels-home-page .switch .switch-input{position:absolute;top:0;left:0;opacity:0}#panels-home-page .switch .switch-label{position:relative;display:block;height:inherit;font-size:12px;text-transform:uppercase;background:#eceeef;border-radius:inherit;box-shadow:inset 0 1px 2px rgba(0,0,0,.12),inset 0 0 2px rgba(0,0,0,.15);transition:.15s ease-out;transition-property:opacity background}#panels-home-page .switch .switch-label:after,#panels-home-page .switch .switch-label:before{position:absolute;top:50%;margin-top:-.5em;line-height:1;transition:inherit}#panels-home-page .switch .switch-label:before{content:attr(data-off);right:11px;color:#aaa;text-shadow:0 1px hsla(0,0%,100%,.5)}#panels-home-page .switch .switch-label:after{content:attr(data-on);left:13px;color:#fff;text-shadow:0 1px rgba(0,0,0,.2);opacity:0}#panels-home-page .switch .switch-input:checked~.switch-label{background:#47a8d8;box-shadow:inset 0 1px 2px rgba(0,0,0,.15),inset 0 0 3px rgba(0,0,0,.2)}#panels-home-page .switch .switch-input:checked~.switch-label:before{opacity:0}#panels-home-page .switch .switch-input:checked~.switch-label:after{opacity:1}#panels-home-page .switch .switch-handle{position:absolute;top:4px;left:4px;width:22px;height:22px;background:#fff;border-radius:12px;box-shadow:1px 1px 5px rgba(0,0,0,.2);background-image:linear-gradient(180deg,#fff 40%,#f0f0f0);transition:left .15s ease-out}#panels-home-page .switch .switch-handle:before{content:"";position:absolute;top:50%;left:50%;margin:-7px 0 0 -7px;width:14px;height:14px;background:#f9f9f9;border-radius:7px;box-shadow:inset 0 1px rgba(0,0,0,.02);background-image:linear-gradient(180deg,#eee,#fff)}#panels-home-page .switch .switch-input:checked~.switch-handle{left:48px;box-shadow:-1px 1px 5px rgba(0,0,0,.2)}#panels-home-page .switch .switch-green>.switch-input:checked~.switch-label{background:#4fb845}#panels-home-page #panels-view-as-page{display:inline-block;margin-left:50px}.siteorigin-panels-builder-form .siteorigin-panels-builder{border:1px solid #d0d0d0;background-color:#fff;margin:10px 0}.siteorigin-panels-builder-form .siteorigin-panels-builder.so-panels-loading{min-height:150px}.siteorigin-page-builder-widget .siteorigin-panels-display-builder{display:inline-block!important}.siteorigin-page-builder-widget .siteorigin-panels-no-builder{display:none!important}.so-panels-contextual-menu{border:1px solid silver;background:#f9f9f9;box-shadow:0 1px 1px rgba(0,0,0,.04);outline:none;border-radius:2px;position:absolute;width:180px;top:20px;left:20px;z-index:999999;display:none;overflow-y:auto}.so-panels-contextual-menu,.so-panels-contextual-menu *{font-size:12px}.so-panels-contextual-menu .so-section{border-bottom:1px solid silver}.so-panels-contextual-menu .so-section:last-child{border-bottom:none}.so-panels-contextual-menu .so-section h5{margin:0 0 5px;padding:8px 10px 5px;border-bottom:1px solid #d0d0d0;background:#f6f6f6}.so-panels-contextual-menu .so-section .so-search-wrapper{margin:-5px 0 5px;border-bottom:1px solid #d0d0d0;background:#f4f4f4}.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]{box-sizing:border-box;display:block;width:100%;margin:0;border:none;padding:5px 10px;background:#fbfbfb}.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]:active,.so-panels-contextual-menu .so-section .so-search-wrapper input[type=text]:focus{border:none;box-shadow:none;background:#fff}.so-panels-contextual-menu .so-section ul{margin:5px 0 0;padding:0 0 5px}.so-panels-contextual-menu .so-section ul li{cursor:pointer;margin:0;padding:4px 10px;line-height:1em}.so-panels-contextual-menu .so-section ul li.so-active,.so-panels-contextual-menu .so-section ul li:hover{background:#f0f0f0;color:#444}.so-panels-contextual-menu .so-section ul li.so-confirm{color:#a00}.so-panels-contextual-menu .so-section ul li.so-confirm.so-active,.so-panels-contextual-menu .so-section ul li.so-confirm:hover{background:#a00;color:#fff}.so-panels-contextual-menu .so-section ul li .dashicons{width:12px;height:12px;font-size:12px;margin:0;float:right;line-height:12px}.so-panels-contextual-menu .so-section .so-no-results{padding:0 10px 5px;display:none;font-style:italic}.so-dropdown-wrapper{position:relative;float:right}.so-dropdown-wrapper .so-dropdown-links-wrapper{position:absolute;padding:6px 0 0}.so-dropdown-wrapper .so-dropdown-links-wrapper ul{margin:0;border:1px solid silver;background:#f9f9f9;border-radius:2px;padding:4px 0;box-shadow:0 2px 2px rgba(0,0,0,.1)}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li{margin:0}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li:first-child{border-top-width:1px}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a{display:block;padding:2px 8px;text-decoration:none;color:#666;font-size:11px;cursor:pointer;outline:0!important;box-shadow:none}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a:hover{background:#f0f0f0;color:#444}.so-dropdown-wrapper .so-dropdown-links-wrapper ul li a .dashicons{font-size:16px;margin:0;float:right;line-height:16px}.so-dropdown-wrapper .so-dropdown-links-wrapper .so-pointer{width:12px;height:6px;position:absolute;z-index:12;background:url(images/dropdown-pointer.png);background-size:12px 6px;top:1px;right:18px}.so-panels-icon{font-family:siteorigin-panels-icons;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.so-panels-icon.so-panels-icon-add-row:before{content:"\e900"}.so-panels-icon.so-panels-icon-add-widget:before{content:"\e901"}.so-panels-icon.so-panels-icon-addons:before{content:"\e902"}.so-panels-icon.so-panels-icon-history:before{content:"\e903"}.so-panels-icon.so-panels-icon-layouts:before{content:"\e904"}.so-panels-icon.so-panels-icon-learn:before{content:"\e905"}.so-panels-icon.so-panels-icon-live-editor:before{content:"\e906"}.so-panels-icon.so-panels-icon-move:before{content:"\e907"}.so-panels-icon.so-panels-icon-settings:before{content:"\e908"}#post-status-info.for-siteorigin-panels{margin-top:-21px!important}
css/front-flex.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-layout.panel-is-rtl .panel-grid.panel-has-style>.panel-row-style,.panel-layout.panel-is-rtl .panel-grid.panel-no-style{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
css/front-legacy.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid{zoom:1}.panel-grid:before{content:"";display:block}.panel-grid:after{content:"";display:table;clear:both}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box;min-height:1em;float:left}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}.panel-row-style{zoom:1}.panel-row-style:before{content:"";display:block}.panel-row-style:after{content:"";display:table;clear:both}
css/front.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .panel-grid.panel-has-style>.panel-row-style,.panel-grid.panel-no-style{display:flex;-ms-flex-wrap:wrap;flex-wrap:nowrap;-ms-justify-content:space-between;justify-content:space-between}.panel-grid-cell{-ms-box-sizing:border-box;box-sizing:border-box}.panel-grid-cell .panel-cell-style{height:100%}.panel-grid-cell .so-panel{zoom:1}.panel-grid-cell .so-panel:before{content:"";display:block}.panel-grid-cell .so-panel:after{content:"";display:table;clear:both}.panel-grid-cell .panel-last-child{margin-bottom:0}.panel-grid-cell .widget-title{margin-top:0}body.siteorigin-panels-before-js{overflow-x:hidden}body.siteorigin-panels-before-js .siteorigin-panels-stretch{margin-right:-1000px!important;margin-left:-1000px!important;padding-right:1000px!important;padding-left:1000px!important}
css/live-editor-front.min.css ADDED
@@ -0,0 +1 @@
 
1
+ .so-panel{transition-duration:.6s!important}.so-panel.so-panels-highlighted{opacity:1!important}.so-panel.so-panels-faded{opacity:.275!important}
css/live-editor-preview.min.css ADDED
@@ -0,0 +1 @@
 
1
+ html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}body,button,input,select,textarea{color:#404040;font-size:14px;line-height:1.5}h1,h2,h3,h4,h5,h6{clear:both}p{margin-bottom:1.5em}cite,dfn,em,i{font-style:italic}blockquote{margin:0 1.5em}address{margin:0 0 1.5em}pre{background:#eee;font-family:Courier\ 10 Pitch,Courier,monospace;line-height:1.6;margin-bottom:1.6em;max-width:100%;overflow:auto;padding:1.6em}code,kbd,pre,tt,var{font-size:15px;font-size:.9375rem}code,kbd,tt,var{font-family:Monaco,Consolas,Andale Mono,DejaVu Sans Mono,monospace}abbr,acronym{border-bottom:1px dotted #666;cursor:help}ins,mark{background:#fff9c0;text-decoration:none}big{font-size:125%}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body{background:#fff}blockquote:after,blockquote:before,q:after,q:before{content:""}blockquote,q{quotes:"" ""}hr{background-color:#ccc;border:0;height:1px;margin-bottom:1.5em}ol,ul{margin:0 0 1.5em 3em}ul{list-style:disc}ol{list-style:decimal}li>ol,li>ul{margin-bottom:0;margin-left:1.5em}dt{font-weight:700}dd{margin:0 1.5em 1.5em}img{height:auto;max-width:100%}table{margin:0 0 1.5em;width:100%}button,input[type=button],input[type=reset],input[type=submit]{border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;background:#e6e6e6;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.5),inset 0 15px 17px hsla(0,0%,100%,.5),inset 0 -5px 12px rgba(0,0,0,.05);color:rgba(0,0,0,.8);font-size:12px;font-size:.75rem;line-height:1;padding:.6em 1em .4em;text-shadow:0 1px 0 hsla(0,0%,100%,.8)}button:hover,input[type=button]:hover,input[type=reset]:hover,input[type=submit]:hover{border-color:#ccc #bbb #aaa;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.8),inset 0 15px 17px hsla(0,0%,100%,.8),inset 0 -5px 12px rgba(0,0,0,.02)}button:active,button:focus,input[type=button]:active,input[type=button]:focus,input[type=reset]:active,input[type=reset]:focus,input[type=submit]:active,input[type=submit]:focus{border-color:#aaa #bbb #bbb;box-shadow:inset 0 -1px 0 hsla(0,0%,100%,.5),inset 0 2px 5px rgba(0,0,0,.15)}input[type=email],input[type=password],input[type=search],input[type=text],input[type=url],textarea{color:#666;border:1px solid #ccc;border-radius:3px}input[type=email]:focus,input[type=password]:focus,input[type=search]:focus,input[type=text]:focus,input[type=url]:focus,textarea:focus{color:#111}input[type=email],input[type=password],input[type=search],input[type=text],input[type=url]{padding:3px}textarea{padding-left:3px;width:100%}a{color:#4169e1}a:visited{color:purple}a:active,a:focus,a:hover{color:#191970}a:focus{outline:thin dotted}a:active,a:hover{outline:0}.main-navigation{clear:both;display:block;float:left;width:100%}.main-navigation ul{display:none;list-style:none;margin:0;padding-left:0}.main-navigation li{float:left;position:relative}.main-navigation a{display:block;text-decoration:none}.main-navigation ul ul{box-shadow:0 3px 3px rgba(0,0,0,.2);float:left;position:absolute;top:1.5em;left:-999em;z-index:99999}.main-navigation ul ul ul{left:-999em;top:0}.main-navigation ul ul a{width:200px}.main-navigation ul li.focus>ul,.main-navigation ul li:hover>ul{left:auto}.main-navigation ul ul li.focus>ul,.main-navigation ul ul li:hover>ul{left:100%}.main-navigation.toggled ul,.menu-toggle{display:block}@media screen and (min-width:37.5em){.menu-toggle{display:none}.main-navigation ul{display:block}}.site-main .comment-navigation,.site-main .post-navigation,.site-main .posts-navigation{margin:0 0 1.5em;overflow:hidden}.comment-navigation .nav-previous,.post-navigation .nav-previous,.posts-navigation .nav-previous{float:left;width:50%}.comment-navigation .nav-next,.post-navigation .nav-next,.posts-navigation .nav-next{float:right;text-align:right;width:50%}.screen-reader-text{clip:rect(1px,1px,1px,1px);position:absolute!important;height:1px;width:1px;overflow:hidden}.screen-reader-text:focus{background-color:#f1f1f1;border-radius:3px;box-shadow:0 0 2px 2px rgba(0,0,0,.6);clip:auto!important;color:#21759b;display:block;font-size:14px;font-size:.875rem;font-weight:700;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}.alignleft{display:inline;float:left;margin-right:1.5em}.alignright{display:inline;float:right;margin-left:1.5em}.aligncenter{clear:both;display:block;margin-left:auto;margin-right:auto}.clear:after,.clear:before,.comment-content:after,.comment-content:before,.entry-content:after,.entry-content:before,.site-content:after,.site-content:before,.site-footer:after,.site-footer:before,.site-header:after,.site-header:before{content:"";display:table}.clear:after,.comment-content:after,.entry-content:after,.site-content:after,.site-footer:after,.site-header:after{clear:both}.widget{margin:0 0 1.5em}.widget select{max-width:100%}.widget_search .search-submit{display:none}.sticky{display:block}.hentry{margin:0 0 1.5em}.byline,.updated:not(.published){display:none}.group-blog .byline,.single .byline{display:inline}.entry-content,.entry-summary,.page-content{margin:1.5em 0 0}.page-links{clear:both;margin:0 0 1.5em}.archive .format-aside .entry-title,.blog .format-aside .entry-title{display:none}.comment-content a{word-wrap:break-word}.bypostauthor{display:block}.infinite-scroll.neverending .site-footer,.infinite-scroll .posts-navigation{display:none}.infinity-end.neverending .site-footer{display:block}.comment-content .wp-smiley,.entry-content .wp-smiley,.page-content .wp-smiley{border:none;margin-bottom:0;margin-top:0;padding:0}.wp-caption,embed,iframe,object{max-width:100%}.wp-caption{margin-bottom:1.5em}.wp-caption img[class*=wp-image-]{display:block;margin:0 auto}.wp-caption-text{text-align:center}.wp-caption .wp-caption-text{margin:.8075em 0}.gallery{margin-bottom:1.5em}.gallery-item{display:inline-block;text-align:center;vertical-align:top;width:100%}.gallery-columns-2 .gallery-item{max-width:50%}.gallery-columns-3 .gallery-item{max-width:33.33%}.gallery-columns-4 .gallery-item{max-width:25%}.gallery-columns-5 .gallery-item{max-width:20%}.gallery-columns-6 .gallery-item{max-width:16.66%}.gallery-columns-7 .gallery-item{max-width:14.28%}.gallery-columns-8 .gallery-item{max-width:12.5%}.gallery-columns-9 .gallery-item{max-width:11.11%}.gallery-caption{display:block}#content{box-sizing:border-box;max-width:1280px;margin:0 auto;padding:20px 40px}
inc/admin-layouts.php CHANGED
@@ -1,463 +1,467 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Panels_Admin
5
- *
6
- * Handles all the admin and database interactions.
7
- */
8
- class SiteOrigin_Panels_Admin_Layouts {
9
-
10
- const LAYOUT_URL = 'http://layouts.siteorigin.com/';
11
-
12
- function __construct() {
13
- // Filter all the available external layout directories.
14
- add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
- // Filter all the available local layout folders.
16
- add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
-
18
- add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
- add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
- add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
- add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
- add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
- }
24
-
25
- /**
26
- * @return SiteOrigin_Panels_Admin_Layouts
27
- */
28
- public static function single() {
29
- static $single;
30
- return empty( $single ) ? $single = new self() : $single;
31
- }
32
-
33
- /**
34
- * Add the main SiteOrigin layout directory
35
- */
36
- public function filter_directories( $directories ){
37
- if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
- $directories['siteorigin'] = array(
39
- // The title of the layouts directory in the sidebar.
40
- 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
- // The URL of the directory.
42
- 'url' => self::LAYOUT_URL,
43
- // Any additional arguments to pass to the layouts server
44
- 'args' => array()
45
- );
46
- }
47
-
48
- return $directories;
49
- }
50
-
51
- /**
52
- * Get all the layout directories.
53
- *
54
- * @return array
55
- */
56
- public function get_directories(){
57
- $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
- if( empty( $directories ) || ! is_array( $directories ) ) {
59
- $directories = array();
60
- }
61
-
62
- return $directories;
63
- }
64
-
65
-
66
- /**
67
- * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
- * prebuilt layouts.
69
- *
70
- */
71
- public function get_local_layouts() {
72
-
73
- // By default we'll look for layouts in a directory in the active theme
74
- $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
-
76
- // And the child theme if there is one.
77
- if ( is_child_theme() ) {
78
- $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
- }
80
-
81
- // This allows themes and plugins to customize where we look for layouts.
82
- $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
-
84
- $layouts = array();
85
- foreach ( $layout_folders as $folder ) {
86
- $files = array();
87
- if ( file_exists( $folder ) && is_dir( $folder ) ) {
88
- $files = list_files( $folder, 1 );
89
- }
90
-
91
- foreach ( $files as $file ) {
92
- // get file mime type
93
- $mime_type = mime_content_type( $file );
94
-
95
- // skip non text files.
96
- if ( strpos( $mime_type, 'text/' ) !== 0 ) {
97
- continue;
98
- }
99
-
100
- // get file contents
101
- $file_contents = file_get_contents( $file );
102
- // json decode
103
- $panels_data = json_decode( $file_contents, true );
104
-
105
- // get file name by stripping out folder path and .json extension
106
- $file_name = str_replace( $folder . '/' , '', $file );
107
- $file_name = str_replace( '.json', '', $file_name );
108
-
109
- // get name: check for id or name else use filename
110
- $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
111
-
112
- if ( empty( $panels_data['name'] ) ) {
113
- $panels_data['name'] = $file_name;
114
- }
115
-
116
- $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
117
-
118
- // get screenshot: check for screenshot prop else try use image file with same filename.
119
- $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
120
-
121
- // set item on layouts array
122
- $layouts[ $panels_data['id'] ] = $panels_data;
123
- }
124
- }
125
-
126
- return $layouts;
127
- }
128
-
129
- private function get_layout_id( $layout_data, $fallback ) {
130
- if ( ! empty( $layout_data['id'] ) ) {
131
- return $layout_data['id'];
132
- } else if ( ! empty( $layout_data['name'] ) ) {
133
- return $layout_data['name'];
134
- } else {
135
- return $fallback;
136
- }
137
- }
138
-
139
- private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
140
- if ( ! empty( $panels_data['screenshot'] ) ) {
141
- return $panels_data['screenshot'];
142
- } else {
143
- $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
144
- // Highlander Condition. There can be only one.
145
- $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
146
- $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
147
- $screenshot_url = '';
148
- if ( file_exists( $screenshot_path ) &&
149
- strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
150
-
151
- $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
152
- }
153
-
154
- return $screenshot_url;
155
- }
156
- }
157
-
158
- /**
159
- * Gets all the prebuilt layouts.
160
- */
161
- function action_get_prebuilt_layouts() {
162
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
163
- wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
164
- }
165
-
166
- // Get any layouts that the current user could edit.
167
- header( 'content-type: application/json' );
168
-
169
- $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
170
- $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
171
- $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
172
-
173
- $return = array(
174
- 'title' => '',
175
- 'items' => array()
176
- );
177
- if ( $type == 'prebuilt' ) {
178
- $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
179
-
180
- // This is for theme bundled prebuilt directories
181
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
182
-
183
- foreach ( $layouts as $id => $vals ) {
184
- if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
185
- continue;
186
- }
187
-
188
- $return['items'][] = array(
189
- 'title' => $vals['name'],
190
- 'id' => $id,
191
- 'type' => 'prebuilt',
192
- 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
193
- 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
194
- );
195
- }
196
-
197
- $return['max_num_pages'] = 1;
198
- } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
199
- $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
200
-
201
- // This is a query of the prebuilt layout directory
202
- $query = array();
203
- if ( ! empty( $search ) ) {
204
- $query['search'] = $search;
205
- }
206
- $query['page'] = $page_num;
207
-
208
- $directory_id = str_replace( 'directory-', '', $type );
209
- $directories = $this->get_directories();
210
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
211
-
212
- if( empty( $directory ) ) {
213
- return false;
214
- }
215
-
216
- $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
217
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
218
- $url = add_query_arg( $directory[ 'args' ], $url );
219
- }
220
-
221
- $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
222
- $response = wp_remote_get( $url );
223
-
224
- if ( is_array( $response ) && $response['response']['code'] == 200 ) {
225
- $results = json_decode( $response['body'], true );
226
- if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
227
- foreach ( $results['items'] as $item ) {
228
- $item['id'] = $item['slug'];
229
- $item['type'] = $type;
230
-
231
- if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
232
- $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
233
- $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
234
- }
235
-
236
- $return['items'][] = $item;
237
- }
238
- }
239
-
240
- $return['max_num_pages'] = $results['max_num_pages'];
241
- }
242
- } elseif ( strpos( $type, 'clone_' ) !== false ) {
243
- // Check that the user can view the given page types
244
- $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
245
- if( empty( $post_type ) ) {
246
- return;
247
- }
248
-
249
- $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
250
-
251
- global $wpdb;
252
- $user_can_read_private = ( $post_type == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type == 'page' && current_user_can( 'read_private_pages' ) ) );
253
- $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
254
-
255
- // Select only the posts with the given post type that also have panels_data
256
- $results = $wpdb->get_results( "
257
- SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
258
- FROM {$wpdb->posts} AS posts
259
- JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
260
- WHERE
261
- posts.post_type = '" . esc_sql( $post_type->name ) . "'
262
- AND meta.meta_key = 'panels_data'
263
- " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
264
- AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
265
- ORDER BY post_date DESC
266
- LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
267
- $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
268
-
269
- foreach ( $results as $result ) {
270
- $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
271
- $return['items'][] = array(
272
- 'id' => $result->ID,
273
- 'title' => $result->post_title,
274
- 'type' => $type,
275
- 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
276
- );
277
- }
278
-
279
- $return['max_num_pages'] = ceil( $total_posts / 16 );
280
-
281
- } else {
282
- // An invalid type. Display an error message.
283
- }
284
-
285
- // Add the search part to the title
286
- if ( ! empty( $search ) ) {
287
- $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
288
- }
289
-
290
- echo json_encode( $return );
291
-
292
- wp_die();
293
- }
294
-
295
- /**
296
- * Ajax handler to get an individual prebuilt layout
297
- */
298
- function action_get_prebuilt_layout() {
299
- if ( empty( $_REQUEST['type'] ) ) {
300
- wp_die();
301
- }
302
- if ( empty( $_REQUEST['lid'] ) ) {
303
- wp_die();
304
- }
305
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
306
- wp_die();
307
- }
308
-
309
- header( 'content-type: application/json' );
310
- $panels_data = array();
311
- $raw_panels_data = false;
312
-
313
- if ( $_REQUEST['type'] == 'prebuilt' ) {
314
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
315
- $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
316
-
317
- if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
318
- wp_send_json_error( array(
319
- 'error' => true,
320
- 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
321
- ) );
322
- }
323
-
324
- $layout = $layouts[ $_REQUEST['lid'] ];
325
-
326
- // Fix the format of this layout
327
- if( !empty( $layout[ 'filename' ] ) ) {
328
- $filename = $layout[ 'filename' ];
329
- // Only accept filenames that end with .json
330
- if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
331
- $panels_data = json_decode( file_get_contents( $filename ), true );
332
- $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
333
- $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
334
- $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
335
- }
336
- }
337
-
338
- // A theme or plugin could use this to change the data in the layout
339
- $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
340
-
341
- // Remove all the layout specific attributes
342
- if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
343
- if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
344
- if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
345
-
346
- $raw_panels_data = true;
347
-
348
- } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
349
- $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
350
- $directories = $this->get_directories();
351
- $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
352
-
353
- if( ! empty( $directory ) ) {
354
- $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
355
- if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
356
- $url = add_query_arg( $directory[ 'args' ], $url );
357
- }
358
-
359
- $response = wp_remote_get( $url );
360
- if ( $response['response']['code'] == 200 ) {
361
- // For now, we'll just pretend to load this
362
- $panels_data = json_decode( $response['body'], true );
363
- } else {
364
- wp_send_json_error( array(
365
- 'error' => true,
366
- 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
367
- ) );
368
- }
369
- }
370
- $raw_panels_data = true;
371
-
372
- } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
373
- $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
374
- }
375
-
376
- if( $raw_panels_data ) {
377
- // This panels_data is flagged as raw, so it needs to be processed.
378
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
379
- $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
380
- }
381
-
382
- wp_send_json_success( $panels_data );
383
- }
384
-
385
- /**
386
- * Ajax handler to import a layout
387
- */
388
- function action_import_layout() {
389
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
390
- wp_die();
391
- }
392
-
393
- if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
394
- header( 'content-type:application/json' );
395
- $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
396
- @unlink( $_FILES['panels_import_data']['tmp_name'] );
397
- echo $json;
398
- }
399
- wp_die();
400
- }
401
-
402
- /**
403
- * Export a given layout as a JSON file.
404
- */
405
- function action_export_layout() {
406
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
407
- wp_die();
408
- }
409
-
410
- $export_data = wp_unslash( $_POST['panels_export_data'] );
411
-
412
- $decoded_export_data = json_decode( $export_data, true );
413
-
414
- if ( ! empty( $decoded_export_data['name'] ) ) {
415
- $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
416
- $filename = $decoded_export_data['id'];
417
- } else {
418
- $filename = 'layout-' . date( 'dmY' );
419
- }
420
-
421
-
422
- header( 'content-type: application/json' );
423
- header( "Content-Disposition: attachment; filename=$filename.json" );
424
-
425
- echo $export_data;
426
-
427
- wp_die();
428
- }
429
-
430
- /**
431
- * Enable the directory.
432
- */
433
- function action_directory_enable() {
434
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
435
- wp_die();
436
- }
437
- $user = get_current_user_id();
438
- update_user_meta( $user, 'so_panels_directory_enabled', true );
439
- wp_die();
440
- }
441
-
442
- /**
443
- * Load a layout from a json file
444
- *
445
- * @param $id
446
- * @param $name
447
- * @param $json_file
448
- * @param bool $screenshot
449
- *
450
- * @return array The data for the layout
451
- */
452
- public static function load_layout($id, $name, $json_file, $screenshot = false) {
453
- $layout_data = json_decode(file_get_contents($json_file), true);
454
- $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
455
-
456
- $layout_data = array_merge(array(
457
- 'name' => $name,
458
- 'screenshot' => $screenshot,
459
- ), $layout_data);
460
-
461
- return $layout_data;
462
- }
463
- }
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Panels_Admin
5
+ *
6
+ * Handles all the admin and database interactions.
7
+ */
8
+ class SiteOrigin_Panels_Admin_Layouts {
9
+
10
+ const LAYOUT_URL = 'http://layouts.siteorigin.com/';
11
+
12
+ function __construct() {
13
+ // Filter all the available external layout directories.
14
+ add_filter( 'siteorigin_panels_external_layout_directories', array( $this, 'filter_directories' ), 8 );
15
+ // Filter all the available local layout folders.
16
+ add_filter( 'siteorigin_panels_prebuilt_layouts', array( $this, 'get_local_layouts' ), 8 );
17
+
18
+ add_action( 'wp_ajax_so_panels_layouts_query', array( $this, 'action_get_prebuilt_layouts' ) );
19
+ add_action( 'wp_ajax_so_panels_get_layout', array( $this, 'action_get_prebuilt_layout' ) );
20
+ add_action( 'wp_ajax_so_panels_import_layout', array( $this, 'action_import_layout' ) );
21
+ add_action( 'wp_ajax_so_panels_export_layout', array( $this, 'action_export_layout' ) );
22
+ add_action( 'wp_ajax_so_panels_directory_enable', array( $this, 'action_directory_enable' ) );
23
+ }
24
+
25
+ /**
26
+ * @return SiteOrigin_Panels_Admin_Layouts
27
+ */
28
+ public static function single() {
29
+ static $single;
30
+ return empty( $single ) ? $single = new self() : $single;
31
+ }
32
+
33
+ /**
34
+ * Add the main SiteOrigin layout directory
35
+ */
36
+ public function filter_directories( $directories ){
37
+ if ( apply_filters( 'siteorigin_panels_layouts_directory_enabled', true ) ) {
38
+ $directories['siteorigin'] = array(
39
+ // The title of the layouts directory in the sidebar.
40
+ 'title' => __( 'Layouts Directory', 'siteorigin-panels' ),
41
+ // The URL of the directory.
42
+ 'url' => self::LAYOUT_URL,
43
+ // Any additional arguments to pass to the layouts server
44
+ 'args' => array()
45
+ );
46
+ }
47
+
48
+ return $directories;
49
+ }
50
+
51
+ /**
52
+ * Get all the layout directories.
53
+ *
54
+ * @return array
55
+ */
56
+ public function get_directories(){
57
+ $directories = apply_filters( 'siteorigin_panels_external_layout_directories', array() );
58
+ if( empty( $directories ) || ! is_array( $directories ) ) {
59
+ $directories = array();
60
+ }
61
+
62
+ return $directories;
63
+ }
64
+
65
+
66
+ /**
67
+ * Looks through local folders in the active theme and any others filtered in by theme and plugins, to find JSON
68
+ * prebuilt layouts.
69
+ *
70
+ */
71
+ public function get_local_layouts() {
72
+
73
+ // By default we'll look for layouts in a directory in the active theme
74
+ $layout_folders = array( get_template_directory() . '/siteorigin-page-builder-layouts' );
75
+
76
+ // And the child theme if there is one.
77
+ if ( is_child_theme() ) {
78
+ $layout_folders[] = get_stylesheet_directory() . '/siteorigin-page-builder-layouts';
79
+ }
80
+
81
+ // This allows themes and plugins to customize where we look for layouts.
82
+ $layout_folders = apply_filters( 'siteorigin_panels_local_layouts_directories', $layout_folders );
83
+
84
+ $layouts = array();
85
+ foreach ( $layout_folders as $folder ) {
86
+ if ( file_exists( $folder ) && is_dir( $folder ) ) {
87
+ $files = list_files( $folder, 1 );
88
+ if ( empty( $files ) ) {
89
+ continue;
90
+ }
91
+
92
+ foreach ( $files as $file ) {
93
+ // get file mime type
94
+ $mime_type = mime_content_type( $file );
95
+
96
+ // skip non text files.
97
+ if ( strpos( $mime_type, 'text/' ) !== 0 ) {
98
+ continue;
99
+ }
100
+
101
+ // get file contents
102
+ $file_contents = file_get_contents( $file );
103
+
104
+ // json decode
105
+ $panels_data = json_decode( $file_contents, true );
106
+
107
+ if ( ! empty( $panels_data ) ) {
108
+ // get file name by stripping out folder path and .json extension
109
+ $file_name = str_replace( array( $folder . '/', '.json' ), '', $file );
110
+
111
+ // get name: check for id or name else use filename
112
+ $panels_data['id'] = sanitize_title_with_dashes( $this->get_layout_id( $panels_data, $file_name ) );
113
+
114
+ if ( empty( $panels_data['name'] ) ) {
115
+ $panels_data['name'] = $file_name;
116
+ }
117
+
118
+ $panels_data['name'] = sanitize_text_field( $panels_data['name'] );
119
+
120
+ // get screenshot: check for screenshot prop else try use image file with same filename.
121
+ $panels_data['screenshot'] = $this->get_layout_file_screenshot( $panels_data, $folder, $file_name );
122
+
123
+ // set item on layouts array
124
+ $layouts[ $panels_data['id'] ] = $panels_data;
125
+ }
126
+ }
127
+ }
128
+ }
129
+
130
+ return $layouts;
131
+ }
132
+
133
+ private function get_layout_id( $layout_data, $fallback ) {
134
+ if ( ! empty( $layout_data['id'] ) ) {
135
+ return $layout_data['id'];
136
+ } else if ( ! empty( $layout_data['name'] ) ) {
137
+ return $layout_data['name'];
138
+ } else {
139
+ return $fallback;
140
+ }
141
+ }
142
+
143
+ private function get_layout_file_screenshot( $panels_data, $folder_path, $file_name ) {
144
+ if ( ! empty( $panels_data['screenshot'] ) ) {
145
+ return $panels_data['screenshot'];
146
+ } else {
147
+ $paths = glob( $folder_path . "/$file_name.{jpg,jpeg,gif,png}", GLOB_BRACE );
148
+ // Highlander Condition. There can be only one.
149
+ $screenshot_path = empty( $paths ) ? '' : wp_normalize_path( $paths[0] );
150
+ $wp_content_dir = wp_normalize_path( WP_CONTENT_DIR );
151
+ $screenshot_url = '';
152
+ if ( file_exists( $screenshot_path ) &&
153
+ strrpos( $screenshot_path, $wp_content_dir ) === 0 ) {
154
+
155
+ $screenshot_url = str_replace( $wp_content_dir, content_url(), $screenshot_path );
156
+ }
157
+
158
+ return $screenshot_url;
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Gets all the prebuilt layouts.
164
+ */
165
+ function action_get_prebuilt_layouts() {
166
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
167
+ wp_die( __( 'Invalid request.', 'siteorigin-panels' ), 403 );
168
+ }
169
+
170
+ // Get any layouts that the current user could edit.
171
+ header( 'content-type: application/json' );
172
+
173
+ $type = ! empty( $_REQUEST['type'] ) ? $_REQUEST['type'] : 'directory-siteorigin';
174
+ $search = ! empty( $_REQUEST['search'] ) ? trim( strtolower( $_REQUEST['search'] ) ) : '';
175
+ $page_num = ! empty( $_REQUEST['page'] ) ? intval( $_REQUEST['page'] ) : 1;
176
+
177
+ $return = array(
178
+ 'title' => '',
179
+ 'items' => array()
180
+ );
181
+ if ( $type == 'prebuilt' ) {
182
+ $return['title'] = __( 'Theme Defined Layouts', 'siteorigin-panels' );
183
+
184
+ // This is for theme bundled prebuilt directories
185
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
186
+
187
+ foreach ( $layouts as $id => $vals ) {
188
+ if ( ! empty( $search ) && strpos( strtolower( $vals['name'] ), $search ) === false ) {
189
+ continue;
190
+ }
191
+
192
+ $return['items'][] = array(
193
+ 'title' => $vals['name'],
194
+ 'id' => $id,
195
+ 'type' => 'prebuilt',
196
+ 'description' => isset( $vals['description'] ) ? $vals['description'] : '',
197
+ 'screenshot' => ! empty( $vals['screenshot'] ) ? $vals['screenshot'] : ''
198
+ );
199
+ }
200
+
201
+ $return['max_num_pages'] = 1;
202
+ } elseif ( substr( $type, 0, 10 ) == 'directory-' ) {
203
+ $return['title'] = __( 'Layouts Directory', 'siteorigin-panels' );
204
+
205
+ // This is a query of the prebuilt layout directory
206
+ $query = array();
207
+ if ( ! empty( $search ) ) {
208
+ $query['search'] = $search;
209
+ }
210
+ $query['page'] = $page_num;
211
+
212
+ $directory_id = str_replace( 'directory-', '', $type );
213
+ $directories = $this->get_directories();
214
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
215
+
216
+ if( empty( $directory ) ) {
217
+ return false;
218
+ }
219
+
220
+ $url = add_query_arg( $query, $directory[ 'url' ] . 'wp-admin/admin-ajax.php?action=query_layouts' );
221
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
222
+ $url = add_query_arg( $directory[ 'args' ], $url );
223
+ }
224
+
225
+ $url = apply_filters( 'siteorigin_panels_layouts_directory_url', $url );
226
+ $response = wp_remote_get( $url );
227
+
228
+ if ( is_array( $response ) && $response['response']['code'] == 200 ) {
229
+ $results = json_decode( $response['body'], true );
230
+ if ( ! empty( $results ) && ! empty( $results['items'] ) ) {
231
+ foreach ( $results['items'] as $item ) {
232
+ $item['id'] = $item['slug'];
233
+ $item['type'] = $type;
234
+
235
+ if( empty( $item['screenshot'] ) && ! empty( $item['preview'] ) ) {
236
+ $preview_url = add_query_arg( 'screenshot', 'true', $item[ 'preview' ] );
237
+ $item['screenshot'] = 'https://s.wordpress.com/mshots/v1/' . urlencode( $preview_url ) . '?w=700';
238
+ }
239
+
240
+ $return['items'][] = $item;
241
+ }
242
+ }
243
+
244
+ $return['max_num_pages'] = $results['max_num_pages'];
245
+ }
246
+ } elseif ( strpos( $type, 'clone_' ) !== false ) {
247
+ // Check that the user can view the given page types
248
+ $post_type = get_post_type_object( str_replace( 'clone_', '', $type ) );
249
+ if( empty( $post_type ) ) {
250
+ return;
251
+ }
252
+
253
+ $return['title'] = sprintf( __( 'Clone %s', 'siteorigin-panels' ), esc_html( $post_type->labels->singular_name ) );
254
+
255
+ global $wpdb;
256
+ $user_can_read_private = ( $post_type == 'post' && current_user_can( 'read_private_posts' ) || ( $post_type == 'page' && current_user_can( 'read_private_pages' ) ) );
257
+ $include_private = $user_can_read_private ? "OR posts.post_status = 'private' " : "";
258
+
259
+ // Select only the posts with the given post type that also have panels_data
260
+ $results = $wpdb->get_results( "
261
+ SELECT SQL_CALC_FOUND_ROWS DISTINCT ID, post_title, meta.meta_value
262
+ FROM {$wpdb->posts} AS posts
263
+ JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
264
+ WHERE
265
+ posts.post_type = '" . esc_sql( $post_type->name ) . "'
266
+ AND meta.meta_key = 'panels_data'
267
+ " . ( ! empty( $search ) ? 'AND posts.post_title LIKE "%' . esc_sql( $search ) . '%"' : '' ) . "
268
+ AND ( posts.post_status = 'publish' OR posts.post_status = 'draft' " . $include_private . ")
269
+ ORDER BY post_date DESC
270
+ LIMIT 16 OFFSET " . intval( ( $page_num - 1 ) * 16 ) );
271
+ $total_posts = $wpdb->get_var( "SELECT FOUND_ROWS();" );
272
+
273
+ foreach ( $results as $result ) {
274
+ $thumbnail = get_the_post_thumbnail_url( $result->ID, array( 400, 300 ) );
275
+ $return['items'][] = array(
276
+ 'id' => $result->ID,
277
+ 'title' => $result->post_title,
278
+ 'type' => $type,
279
+ 'screenshot' => ! empty( $thumbnail ) ? $thumbnail : ''
280
+ );
281
+ }
282
+
283
+ $return['max_num_pages'] = ceil( $total_posts / 16 );
284
+
285
+ } else {
286
+ // An invalid type. Display an error message.
287
+ }
288
+
289
+ // Add the search part to the title
290
+ if ( ! empty( $search ) ) {
291
+ $return['title'] .= __( ' - Results For:', 'siteorigin-panels' ) . ' <em>' . esc_html( $search ) . '</em>';
292
+ }
293
+
294
+ echo json_encode( $return );
295
+
296
+ wp_die();
297
+ }
298
+
299
+ /**
300
+ * Ajax handler to get an individual prebuilt layout
301
+ */
302
+ function action_get_prebuilt_layout() {
303
+ if ( empty( $_REQUEST['type'] ) ) {
304
+ wp_die();
305
+ }
306
+ if ( empty( $_REQUEST['lid'] ) ) {
307
+ wp_die();
308
+ }
309
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
310
+ wp_die();
311
+ }
312
+
313
+ header( 'content-type: application/json' );
314
+ $panels_data = array();
315
+ $raw_panels_data = false;
316
+
317
+ if ( $_REQUEST['type'] == 'prebuilt' ) {
318
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
319
+ $lid = ! empty( $_REQUEST['lid'] ) ? $_REQUEST['lid'] : false;
320
+
321
+ if ( empty( $lid ) || empty( $layouts[ $lid ] ) ) {
322
+ wp_send_json_error( array(
323
+ 'error' => true,
324
+ 'message' => __( 'Missing layout ID or no such layout exists', 'siteorigin-panels' ),
325
+ ) );
326
+ }
327
+
328
+ $layout = $layouts[ $_REQUEST['lid'] ];
329
+
330
+ // Fix the format of this layout
331
+ if( !empty( $layout[ 'filename' ] ) ) {
332
+ $filename = $layout[ 'filename' ];
333
+ // Only accept filenames that end with .json
334
+ if( substr( $filename, -5, 5 ) === '.json' && file_exists( $filename ) ) {
335
+ $panels_data = json_decode( file_get_contents( $filename ), true );
336
+ $layout[ 'widgets' ] = ! empty( $panels_data[ 'widgets' ] ) ? $panels_data[ 'widgets' ] : array();
337
+ $layout[ 'grids' ] = ! empty( $panels_data[ 'grids' ] ) ? $panels_data[ 'grids' ] : array();
338
+ $layout[ 'grid_cells' ] = ! empty( $panels_data[ 'grid_cells' ] ) ? $panels_data[ 'grid_cells' ] : array();
339
+ }
340
+ }
341
+
342
+ // A theme or plugin could use this to change the data in the layout
343
+ $panels_data = apply_filters( 'siteorigin_panels_prebuilt_layout', $layout, $lid );
344
+
345
+ // Remove all the layout specific attributes
346
+ if ( isset( $panels_data['name'] ) ) unset( $panels_data['name'] );
347
+ if ( isset( $panels_data['screenshot'] ) ) unset( $panels_data['screenshot'] );
348
+ if ( isset( $panels_data['filename'] ) ) unset( $panels_data['filename'] );
349
+
350
+ $raw_panels_data = true;
351
+
352
+ } elseif ( substr( $_REQUEST['type'], 0, 10 ) == 'directory-' ) {
353
+ $directory_id = str_replace( 'directory-', '', $_REQUEST['type'] );
354
+ $directories = $this->get_directories();
355
+ $directory = ! empty( $directories[ $directory_id ] ) ? $directories[ $directory_id ] : false;
356
+
357
+ if( ! empty( $directory ) ) {
358
+ $url = $directory[ 'url' ] . 'layout/' . urlencode( $_REQUEST[ 'lid' ] ) . '/?action=download';
359
+ if( ! empty( $directory[ 'args' ] ) && is_array( $directory[ 'args' ] ) ) {
360
+ $url = add_query_arg( $directory[ 'args' ], $url );
361
+ }
362
+
363
+ $response = wp_remote_get( $url );
364
+ if ( $response['response']['code'] == 200 ) {
365
+ // For now, we'll just pretend to load this
366
+ $panels_data = json_decode( $response['body'], true );
367
+ } else {
368
+ wp_send_json_error( array(
369
+ 'error' => true,
370
+ 'message' => __( 'There was a problem fetching the layout. Please try again later.', 'siteorigin-panels' ),
371
+ ) );
372
+ }
373
+ }
374
+ $raw_panels_data = true;
375
+
376
+ } elseif ( current_user_can( 'edit_post', $_REQUEST['lid'] ) ) {
377
+ $panels_data = get_post_meta( $_REQUEST['lid'], 'panels_data', true );
378
+ }
379
+
380
+ if( $raw_panels_data ) {
381
+ // This panels_data is flagged as raw, so it needs to be processed.
382
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, false );
383
+ $panels_data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $panels_data['widgets'], array(), true, true );
384
+ }
385
+
386
+ wp_send_json_success( $panels_data );
387
+ }
388
+
389
+ /**
390
+ * Ajax handler to import a layout
391
+ */
392
+ function action_import_layout() {
393
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
394
+ wp_die();
395
+ }
396
+
397
+ if ( ! empty( $_FILES['panels_import_data']['tmp_name'] ) ) {
398
+ header( 'content-type:application/json' );
399
+ $json = file_get_contents( $_FILES['panels_import_data']['tmp_name'] );
400
+ @unlink( $_FILES['panels_import_data']['tmp_name'] );
401
+ echo $json;
402
+ }
403
+ wp_die();
404
+ }
405
+
406
+ /**
407
+ * Export a given layout as a JSON file.
408
+ */
409
+ function action_export_layout() {
410
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
411
+ wp_die();
412
+ }
413
+
414
+ $export_data = wp_unslash( $_POST['panels_export_data'] );
415
+
416
+ $decoded_export_data = json_decode( $export_data, true );
417
+
418
+ if ( ! empty( $decoded_export_data['name'] ) ) {
419
+ $decoded_export_data['id'] = sanitize_title_with_dashes( $decoded_export_data['name'] );
420
+ $filename = $decoded_export_data['id'];
421
+ } else {
422
+ $filename = 'layout-' . date( 'dmY' );
423
+ }
424
+
425
+
426
+ header( 'content-type: application/json' );
427
+ header( "Content-Disposition: attachment; filename=$filename.json" );
428
+
429
+ echo $export_data;
430
+
431
+ wp_die();
432
+ }
433
+
434
+ /**
435
+ * Enable the directory.
436
+ */
437
+ function action_directory_enable() {
438
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
439
+ wp_die();
440
+ }
441
+ $user = get_current_user_id();
442
+ update_user_meta( $user, 'so_panels_directory_enabled', true );
443
+ wp_die();
444
+ }
445
+
446
+ /**
447
+ * Load a layout from a json file
448
+ *
449
+ * @param $id
450
+ * @param $name
451
+ * @param $json_file
452
+ * @param bool $screenshot
453
+ *
454
+ * @return array The data for the layout
455
+ */
456
+ public static function load_layout($id, $name, $json_file, $screenshot = false) {
457
+ $layout_data = json_decode(file_get_contents($json_file), true);
458
+ $layout_data = apply_filters('siteorigin_panels_load_layout_' . $id, $layout_data);
459
+
460
+ $layout_data = array_merge(array(
461
+ 'name' => $name,
462
+ 'screenshot' => $screenshot,
463
+ ), $layout_data);
464
+
465
+ return $layout_data;
466
+ }
467
+ }
inc/admin-widget-dialog.php CHANGED
@@ -1,193 +1,193 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Admin_Widget_Dialog {
4
-
5
- function __construct() {
6
- add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
7
- add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
8
- }
9
-
10
- /**
11
- * @return SiteOrigin_Panels_Admin
12
- */
13
- public static function single() {
14
- static $single;
15
- return empty( $single ) ? $single = new self() : $single;
16
- }
17
-
18
- /**
19
- * Add some default recommended widgets.
20
- *
21
- * @param $widgets
22
- *
23
- * @return array
24
- */
25
- function add_recommended_widgets( $widgets ) {
26
-
27
- if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
28
- $widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
29
- $widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
30
- }
31
-
32
- if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
33
- // Add in all the widgets bundle widgets
34
- $widgets = wp_parse_args(
35
- $widgets,
36
- include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
37
- );
38
- }
39
-
40
- foreach ( $widgets as $class => $data ) {
41
- if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
42
- $widgets[ $class ]['groups'] = array( 'panels' );
43
- }
44
- }
45
-
46
- if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
47
- $widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
48
- }
49
-
50
- $wordpress_widgets = array(
51
- 'WP_Widget_Pages',
52
- 'WP_Widget_Links',
53
- 'WP_Widget_Search',
54
- 'WP_Widget_Archives',
55
- 'WP_Widget_Meta',
56
- 'WP_Widget_Calendar',
57
- 'WP_Widget_Text',
58
- 'WP_Widget_Categories',
59
- 'WP_Widget_Recent_Posts',
60
- 'WP_Widget_Recent_Comments',
61
- 'WP_Widget_RSS',
62
- 'WP_Widget_Tag_Cloud',
63
- 'WP_Nav_Menu_Widget',
64
- );
65
-
66
- foreach ( $wordpress_widgets as $wordpress_widget ) {
67
- if ( isset( $widgets[ $wordpress_widget ] ) ) {
68
- $widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
69
- $widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
70
- }
71
- }
72
-
73
- // Third-party plugins dettection.
74
- foreach ( $widgets as $widget_id => &$widget ) {
75
- if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
76
- $widget['groups'][] = 'woocommerce';
77
- }
78
- if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
79
- $widget['groups'][] = 'bbpress';
80
- }
81
- if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
82
- $widget['groups'][] = 'jetpack';
83
- }
84
- }
85
-
86
- return $widgets;
87
- }
88
-
89
- /**
90
- * Add tabs to the widget dialog
91
- *
92
- * @param $tabs
93
- *
94
- * @return array
95
- */
96
- function add_widgets_dialog_tabs( $tabs ) {
97
-
98
- $tabs['widgets_bundle'] = array(
99
- 'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
100
- 'filter' => array(
101
- 'groups' => array( 'so-widgets-bundle' )
102
- )
103
- );
104
-
105
- if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
106
- // Add a message about enabling more widgets
107
- $tabs['widgets_bundle']['message'] = preg_replace(
108
- array(
109
- '/1\{ *(.*?) *\}/'
110
- ),
111
- array(
112
- '<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
113
- ),
114
- __( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
115
- );
116
- } else {
117
- // Add a message about installing the widgets bundle
118
- $tabs['widgets_bundle']['message'] = preg_replace(
119
- '/1\{ *(.*?) *\}/',
120
- '<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
121
- __( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
122
- );
123
- }
124
-
125
- // Add the Widgets Bundle message to the main widgets tab
126
- $tabs[0]['message'] = $tabs['widgets_bundle']['message'];
127
-
128
- $tabs['page_builder'] = array(
129
- 'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
130
- 'message' => preg_replace(
131
- array(
132
- '/1\{ *(.*?) *\}/'
133
- ),
134
- array(
135
- '<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
136
- ),
137
- __( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
138
- ),
139
- 'filter' => array(
140
- 'groups' => array( 'panels' )
141
- )
142
- );
143
-
144
- $tabs['wordpress'] = array(
145
- 'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
146
- 'filter' => array(
147
- 'groups' => array( 'wordpress' )
148
- )
149
- );
150
-
151
- // Check for woocommerce plugin.
152
- if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
153
- $tabs['woocommerce'] = array(
154
- // TRANSLATORS: The name of WordPress plugin
155
- 'title' => __( 'WooCommerce', 'woocommerce' ),
156
- 'filter' => array(
157
- 'groups' => array( 'woocommerce' )
158
- )
159
- );
160
- }
161
-
162
- // Check for jetpack plugin.
163
- if ( defined( 'JETPACK__VERSION' ) ) {
164
- $tabs['jetpack'] = array(
165
- // TRANSLATORS: The name of WordPress plugin
166
- 'title' => __( 'Jetpack', 'jetpack' ),
167
- 'filter' => array(
168
- 'groups' => array( 'jetpack' )
169
- ),
170
- );
171
- }
172
-
173
- // Check for bbpress plugin.
174
- if ( function_exists( 'bbpress' ) ) {
175
- $tabs['bbpress'] = array(
176
- // TRANSLATORS: The name of WordPress plugin
177
- 'title' => __( 'BBPress', 'bbpress' ),
178
- 'filter' => array(
179
- 'groups' => array( 'bbpress' )
180
- ),
181
- );
182
- }
183
-
184
- $tabs['recommended'] = array(
185
- 'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
186
- 'filter' => array(
187
- 'groups' => array( 'recommended' )
188
- )
189
- );
190
-
191
- return $tabs;
192
- }
193
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Admin_Widget_Dialog {
4
+
5
+ function __construct() {
6
+ add_filter( 'siteorigin_panels_widgets', array( $this, 'add_recommended_widgets' ) );
7
+ add_filter( 'siteorigin_panels_widget_dialog_tabs', array( $this, 'add_widgets_dialog_tabs' ), 20 );
8
+ }
9
+
10
+ /**
11
+ * @return SiteOrigin_Panels_Admin
12
+ */
13
+ public static function single() {
14
+ static $single;
15
+ return empty( $single ) ? $single = new self() : $single;
16
+ }
17
+
18
+ /**
19
+ * Add some default recommended widgets.
20
+ *
21
+ * @param $widgets
22
+ *
23
+ * @return array
24
+ */
25
+ function add_recommended_widgets( $widgets ) {
26
+
27
+ if ( ! empty( $widgets['WP_Widget_Black_Studio_TinyMCE'] ) ) {
28
+ $widgets['WP_Widget_Black_Studio_TinyMCE']['groups'] = array( 'recommended' );
29
+ $widgets['WP_Widget_Black_Studio_TinyMCE']['icon'] = 'dashicons dashicons-edit';
30
+ }
31
+
32
+ if ( siteorigin_panels_setting( 'recommended-widgets' ) ) {
33
+ // Add in all the widgets bundle widgets
34
+ $widgets = wp_parse_args(
35
+ $widgets,
36
+ include plugin_dir_path( __FILE__ ) . 'data/widgets-bundle.php'
37
+ );
38
+ }
39
+
40
+ foreach ( $widgets as $class => $data ) {
41
+ if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 || strpos( $class, 'SiteOrigin_Panels_Widget_' ) === 0 ) {
42
+ $widgets[ $class ]['groups'] = array( 'panels' );
43
+ }
44
+ }
45
+
46
+ if ( ! empty( $widgets['SiteOrigin_Panels_Widgets_Layout'] ) ) {
47
+ $widgets['SiteOrigin_Panels_Widgets_Layout']['icon'] = 'dashicons dashicons-analytics';
48
+ }
49
+
50
+ $wordpress_widgets = array(
51
+ 'WP_Widget_Pages',
52
+ 'WP_Widget_Links',
53
+ 'WP_Widget_Search',
54
+ 'WP_Widget_Archives',
55
+ 'WP_Widget_Meta',
56
+ 'WP_Widget_Calendar',
57
+ 'WP_Widget_Text',
58
+ 'WP_Widget_Categories',
59
+ 'WP_Widget_Recent_Posts',
60
+ 'WP_Widget_Recent_Comments',
61
+ 'WP_Widget_RSS',
62
+ 'WP_Widget_Tag_Cloud',
63
+ 'WP_Nav_Menu_Widget',
64
+ );
65
+
66
+ foreach ( $wordpress_widgets as $wordpress_widget ) {
67
+ if ( isset( $widgets[ $wordpress_widget ] ) ) {
68
+ $widgets[ $wordpress_widget ]['groups'] = array( 'wordpress' );
69
+ $widgets[ $wordpress_widget ]['icon'] = 'dashicons dashicons-wordpress';
70
+ }
71
+ }
72
+
73
+ // Third-party plugins dettection.
74
+ foreach ( $widgets as $widget_id => &$widget ) {
75
+ if ( strpos( $widget_id, 'WC_' ) === 0 || strpos( $widget_id, 'WooCommerce' ) !== false ) {
76
+ $widget['groups'][] = 'woocommerce';
77
+ }
78
+ if ( strpos( $widget_id, 'BBP_' ) === 0 || strpos( $widget_id, 'BBPress' ) !== false ) {
79
+ $widget['groups'][] = 'bbpress';
80
+ }
81
+ if ( strpos( $widget_id, 'Jetpack' ) !== false || strpos( $widget['title'], 'Jetpack' ) !== false ) {
82
+ $widget['groups'][] = 'jetpack';
83
+ }
84
+ }
85
+
86
+ return $widgets;
87
+ }
88
+
89
+ /**
90
+ * Add tabs to the widget dialog
91
+ *
92
+ * @param $tabs
93
+ *
94
+ * @return array
95
+ */
96
+ function add_widgets_dialog_tabs( $tabs ) {
97
+
98
+ $tabs['widgets_bundle'] = array(
99
+ 'title' => __( 'Widgets Bundle', 'siteorigin-panels' ),
100
+ 'filter' => array(
101
+ 'groups' => array( 'so-widgets-bundle' )
102
+ )
103
+ );
104
+
105
+ if ( class_exists( 'SiteOrigin_Widgets_Bundle' ) ) {
106
+ // Add a message about enabling more widgets
107
+ $tabs['widgets_bundle']['message'] = preg_replace(
108
+ array(
109
+ '/1\{ *(.*?) *\}/'
110
+ ),
111
+ array(
112
+ '<a href="' . admin_url( 'plugins.php?page=so-widgets-plugins' ) . '">$1</a>'
113
+ ),
114
+ __( 'Enable more widgets in the 1{Widgets Bundle settings}.', 'siteorigin-panels' )
115
+ );
116
+ } else {
117
+ // Add a message about installing the widgets bundle
118
+ $tabs['widgets_bundle']['message'] = preg_replace(
119
+ '/1\{ *(.*?) *\}/',
120
+ '<a href="' . siteorigin_panels_plugin_activation_install_url( 'so-widgets-bundle', __( 'SiteOrigin Widgets Bundle', 'siteorigin-panels' ) ) . '">$1</a>',
121
+ __( 'Install the 1{Widgets Bundle} to get extra widgets.', 'siteorigin-panels' )
122
+ );
123
+ }
124
+
125
+ // Add the Widgets Bundle message to the main widgets tab
126
+ $tabs[0]['message'] = $tabs['widgets_bundle']['message'];
127
+
128
+ $tabs['page_builder'] = array(
129
+ 'title' => __( 'Page Builder Widgets', 'siteorigin-panels' ),
130
+ 'message' => preg_replace(
131
+ array(
132
+ '/1\{ *(.*?) *\}/'
133
+ ),
134
+ array(
135
+ '<a href="' . admin_url( 'options-general.php?page=siteorigin_panels' ) . '">$1</a>'
136
+ ),
137
+ __( 'You can enable the legacy (PB) widgets in the 1{Page Builder settings}.', 'siteorigin-panels' )
138
+ ),
139
+ 'filter' => array(
140
+ 'groups' => array( 'panels' )
141
+ )
142
+ );
143
+
144
+ $tabs['wordpress'] = array(
145
+ 'title' => __( 'WordPress Widgets', 'siteorigin-panels' ),
146
+ 'filter' => array(
147
+ 'groups' => array( 'wordpress' )
148
+ )
149
+ );
150
+
151
+ // Check for woocommerce plugin.
152
+ if ( defined( 'WOOCOMMERCE_VERSION' ) ) {
153
+ $tabs['woocommerce'] = array(
154
+ // TRANSLATORS: The name of WordPress plugin
155
+ 'title' => __( 'WooCommerce', 'woocommerce' ),
156
+ 'filter' => array(
157
+ 'groups' => array( 'woocommerce' )
158
+ )
159
+ );
160
+ }
161
+
162
+ // Check for jetpack plugin.
163
+ if ( defined( 'JETPACK__VERSION' ) ) {
164
+ $tabs['jetpack'] = array(
165
+ // TRANSLATORS: The name of WordPress plugin
166
+ 'title' => __( 'Jetpack', 'jetpack' ),
167
+ 'filter' => array(
168
+ 'groups' => array( 'jetpack' )
169
+ ),
170
+ );
171
+ }
172
+
173
+ // Check for bbpress plugin.
174
+ if ( function_exists( 'bbpress' ) ) {
175
+ $tabs['bbpress'] = array(
176
+ // TRANSLATORS: The name of WordPress plugin
177
+ 'title' => __( 'BBPress', 'bbpress' ),
178
+ 'filter' => array(
179
+ 'groups' => array( 'bbpress' )
180
+ ),
181
+ );
182
+ }
183
+
184
+ $tabs['recommended'] = array(
185
+ 'title' => __( 'Recommended Widgets', 'siteorigin-panels' ),
186
+ 'filter' => array(
187
+ 'groups' => array( 'recommended' )
188
+ )
189
+ );
190
+
191
+ return $tabs;
192
+ }
193
+ }
inc/admin.php CHANGED
@@ -1,1188 +1,1188 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Panels_Admin
5
- *
6
- * Handles all the admin and database interactions.
7
- */
8
- class SiteOrigin_Panels_Admin {
9
-
10
- /**
11
- * @var bool Store that we're in the save post action, to prevent infinite loops
12
- */
13
- private $in_save_post;
14
-
15
- function __construct() {
16
-
17
- add_action( 'plugin_action_links_siteorigin-panels/siteorigin-panels.php', array(
18
- $this,
19
- 'plugin_action_links'
20
- ) );
21
-
22
- add_action( 'current_screen', array( $this, 'admin_init' ) );
23
-
24
- add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
25
- add_action( 'admin_init', array( $this, 'save_home_page' ) );
26
- add_action( 'save_post', array( $this, 'save_post' ) );
27
-
28
- add_action( 'after_switch_theme', array( $this, 'update_home_on_theme_change' ) );
29
-
30
- // Enqueuing admin scripts
31
- add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_admin_scripts' ) );
32
- add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_admin_scripts' ) );
33
- add_action( 'admin_print_scripts-appearance_page_so_panels_home_page', array(
34
- $this,
35
- 'enqueue_admin_scripts'
36
- ) );
37
- add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
38
- add_action( 'admin_print_scripts-edit.php', array( $this, 'footer_column_css' ) );
39
-
40
- // Enqueue the admin styles
41
- add_action( 'admin_print_styles-post-new.php', array( $this, 'enqueue_admin_styles' ) );
42
- add_action( 'admin_print_styles-post.php', array( $this, 'enqueue_admin_styles' ) );
43
- add_action( 'admin_print_styles-appearance_page_so_panels_home_page', array( $this, 'enqueue_admin_styles' ) );
44
- add_action( 'admin_print_styles-widgets.php', array( $this, 'enqueue_admin_styles' ) );
45
-
46
- // The help tab
47
- add_action( 'load-page.php', array( $this, 'add_help_tab' ), 12 );
48
- add_action( 'load-post-new.php', array( $this, 'add_help_tab' ), 12 );
49
- add_action( 'load-appearance_page_so_panels_home_page', array( $this, 'add_help_tab' ), 12 );
50
-
51
- add_action( 'customize_controls_print_footer_scripts', array( $this, 'js_templates' ) );
52
-
53
- // Register all the admin actions
54
- add_action( 'wp_ajax_so_panels_builder_content', array( $this, 'action_builder_content' ) );
55
- add_action( 'wp_ajax_so_panels_widget_form', array( $this, 'action_widget_form' ) );
56
- add_action( 'wp_ajax_so_panels_live_editor_preview', array( $this, 'action_live_editor_preview' ) );
57
-
58
- // Initialize the additional admin classes.
59
- SiteOrigin_Panels_Admin_Widget_Dialog::single();
60
- SiteOrigin_Panels_Admin_Widgets_Bundle::single();
61
- SiteOrigin_Panels_Admin_Layouts::single();
62
-
63
- $this->in_save_post = false;
64
-
65
- add_filter( 'gutenberg_can_edit_post_type', array( $this, 'disable_gutenberg_for_panels_posts' ), 10, 2 );
66
- add_filter( 'filter_gutenberg_meta_boxes', array( $this, 'disable_panels_for_gutenberg_posts' ) );
67
- }
68
-
69
- /**
70
- * @return SiteOrigin_Panels_Admin
71
- */
72
- public static function single() {
73
- static $single;
74
- return empty( $single ) ? $single = new self() : $single;
75
- }
76
-
77
- /**
78
- * Do some general admin initialization
79
- */
80
- public function admin_init(){
81
- if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
82
-
83
- // Add the custom columns
84
- $post_types = siteorigin_panels_setting( 'post-types' );
85
- if( ! empty( $post_types ) ) {
86
- foreach( $post_types as $post_type ) {
87
- add_filter( 'manage_' . $post_type . 's_columns' , array( $this, 'add_custom_column' ) );
88
- add_action( 'manage_' . $post_type . 's_custom_column' , array( $this, 'display_custom_column' ), 10, 2 );
89
- }
90
- }
91
- }
92
-
93
- if( self::is_admin() ) {
94
- // Setup everything for Page Builder learning as long as we're viewing a Page Builder page
95
- SiteOrigin_Learn_Dialog::single();
96
- add_filter( 'siteorigin_learn_lessons', array( $this, 'filter_learn_lessons' ) );
97
- add_filter( 'siteorigin_learn_strings', array( $this, 'filter_learn_strings' ), 99 );
98
- }
99
- }
100
-
101
- /**
102
- * Check if this is an admin page.
103
- *
104
- * @return mixed|void
105
- */
106
- static function is_admin() {
107
- $screen = get_current_screen();
108
- $is_panels_page = ( $screen->base == 'post' && in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) ) || $screen->base == 'appearance_page_so_panels_home_page' || $screen->base == 'widgets' || $screen->base == 'customize';
109
-
110
- return apply_filters( 'siteorigin_panels_is_admin_page', $is_panels_page );
111
- }
112
-
113
- /**
114
- * Add action links to the plugin list for Page Builder.
115
- *
116
- * @param $links
117
- *
118
- * @return array
119
- */
120
- function plugin_action_links( $links ) {
121
- if( ! is_array( $links ) ) {
122
- return $links;
123
- }
124
-
125
- unset( $links['edit'] );
126
- $links[] = '<a href="http://siteorigin.com/threads/plugin-page-builder/">' . __( 'Support Forum', 'siteorigin-panels' ) . '</a>';
127
- $links[] = '<a href="http://siteorigin.com/page-builder/#newsletter">' . __( 'Newsletter', 'siteorigin-panels' ) . '</a>';
128
-
129
- if( SiteOrigin_Panels::display_premium_teaser() ) {
130
- $links[] = '<a href="' . esc_url( SiteOrigin_Panels::premium_url() ) . '" style="color: #3db634" target="_blank" rel="noopener noreferrer">' . __('Addons', 'siteorigin-panels') . '</a>';
131
- }
132
-
133
- return $links;
134
- }
135
-
136
- /**
137
- * Callback to register the Page Builder Metaboxes
138
- */
139
- function add_meta_boxes() {
140
- foreach ( siteorigin_panels_setting( 'post-types' ) as $type ) {
141
- add_meta_box(
142
- 'so-panels-panels',
143
- __( 'Page Builder', 'siteorigin-panels' ),
144
- array( $this, 'render_meta_boxes' ),
145
- ( string ) $type,
146
- 'advanced',
147
- 'high'
148
- );
149
- }
150
- }
151
-
152
- /**
153
- * Render a panel metabox.
154
- *
155
- * @param $post
156
- */
157
- function render_meta_boxes( $post ) {
158
- $panels_data = $this->get_current_admin_panels_data();
159
- include plugin_dir_path( __FILE__ ) . '../tpl/metabox-panels.php';
160
- }
161
-
162
- /**
163
- * Save the panels data
164
- *
165
- * @param $post_id
166
- * @param $post
167
- *
168
- * @action save_post
169
- */
170
- function save_post( $post_id ) {
171
- // Check that everything is valid with this save.
172
- if(
173
- $this->in_save_post ||
174
- ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ||
175
- empty( $_POST['_sopanels_nonce'] ) ||
176
- ! wp_verify_nonce( $_POST['_sopanels_nonce'], 'save' ) ||
177
- ! current_user_can( 'edit_post', $post_id ) ||
178
- ! isset( $_POST['panels_data'] )
179
- ) {
180
- return;
181
- }
182
- $this->in_save_post = true;
183
- // Get post from db as it might have been changed and saved by other plugins.
184
- $post = get_post( $post_id );
185
- $old_panels_data = get_post_meta( $post_id, 'panels_data', true );
186
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
187
-
188
- $panels_data['widgets'] = $this->process_raw_widgets(
189
- $panels_data['widgets'],
190
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
191
- false
192
- );
193
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
194
- $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $post, $post_id );
195
-
196
- if ( ! empty( $panels_data['widgets'] ) || ! empty( $panels_data['grids'] ) ) {
197
- // Use `update_metadata` instead of `update_post_meta` to prevent saving to parent post when it's a revision, e.g. preview.
198
- update_metadata( 'post', $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
199
-
200
- if( siteorigin_panels_setting( 'copy-content' ) ) {
201
- // Store a version of the HTML in post_content
202
- SiteOrigin_Panels_Post_Content_Filters::add_filters();
203
- $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
204
- $post_content = SiteOrigin_Panels::renderer()->render( $post_id, false, $panels_data );
205
- $post_css = SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data );
206
- SiteOrigin_Panels_Post_Content_Filters::remove_filters();
207
- unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
208
-
209
- // Update the post_content
210
- $post->post_content = $post_content;
211
- if( siteorigin_panels_setting( 'copy-styles' ) ) {
212
- $post->post_content .= "\n\n";
213
- $post->post_content .= '<style type="text/css" class="panels-style" data-panels-style-for-post="' . intval( $post_id ) . '">';
214
- $post->post_content .= '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
215
- $post->post_content .= $post_css;
216
- $post->post_content .= '</style>';
217
- }
218
- wp_update_post( $post );
219
- }
220
-
221
- } else {
222
- // There are no widgets or rows, so delete the panels data
223
- delete_post_meta( $post_id, 'panels_data' );
224
- }
225
-
226
- $this->in_save_post = false;
227
- }
228
-
229
- /**
230
- * Enqueue the panels admin scripts
231
- *
232
- * @param string $prefix
233
- * @param bool $force Should we force the enqueues
234
- *
235
- * @action admin_print_scripts-post-new.php
236
- * @action admin_print_scripts-post.php
237
- * @action admin_print_scripts-appearance_page_so_panels_home_page
238
- */
239
- function enqueue_admin_scripts( $prefix = '', $force = false ) {
240
- $screen = get_current_screen();
241
- if ( $force || self::is_admin() ) {
242
- // Media is required for row styles
243
- wp_enqueue_media();
244
- wp_enqueue_script(
245
- 'so-panels-admin',
246
- siteorigin_panels_url( 'js/siteorigin-panels' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
247
- array(
248
- 'jquery',
249
- 'jquery-ui-resizable',
250
- 'jquery-ui-sortable',
251
- 'jquery-ui-draggable',
252
- 'underscore',
253
- 'backbone',
254
- 'plupload',
255
- 'plupload-all'
256
- ),
257
- SITEORIGIN_PANELS_VERSION,
258
- true
259
- );
260
- add_action( 'admin_footer', array( $this, 'js_templates' ) );
261
-
262
- $widgets = $this->get_widgets();
263
- $directory_enabled = get_user_meta( get_current_user_id(), 'so_panels_directory_enabled', true );
264
-
265
- // This is the widget we'll use for default text
266
- if( ! empty( $widgets[ 'SiteOrigin_Widget_Editor_Widget' ] ) ) $text_widget = 'SiteOrigin_Widget_Editor_Widget';
267
- else if( ! empty( $widgets[ 'WP_Widget_Text' ] ) ) $text_widget = 'WP_Widget_Text';
268
- else $text_widget = false;
269
- $text_widget = apply_filters( 'siteorigin_panels_text_widget_class', $text_widget );
270
-
271
- $user = wp_get_current_user();
272
- wp_localize_script( 'so-panels-admin', 'panelsOptions', array(
273
- 'user' => ! empty( $user ) ? $user->ID : 0,
274
- 'ajaxurl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
275
- 'widgets' => $widgets,
276
- 'text_widget' => $text_widget,
277
- 'widget_dialog_tabs' => apply_filters( 'siteorigin_panels_widget_dialog_tabs', array(
278
- 0 => array(
279
- 'title' => __( 'All Widgets', 'siteorigin-panels' ),
280
- 'filter' => array(
281
- 'installed' => true,
282
- 'groups' => ''
283
- )
284
- )
285
- ) ),
286
- 'row_layouts' => apply_filters( 'siteorigin_panels_row_layouts', array() ),
287
- 'directory_enabled' => ! empty( $directory_enabled ),
288
- 'copy_content' => siteorigin_panels_setting( 'copy-content' ),
289
- 'cache' => array(),
290
-
291
- // Settings for the contextual menu
292
- 'contextual' => array(
293
- // Developers can change which widgets are displayed by default using this filter
294
- 'default_widgets' => apply_filters( 'siteorigin_panels_contextual_default_widgets', array(
295
- 'SiteOrigin_Widget_Editor_Widget',
296
- 'SiteOrigin_Widget_Button_Widget',
297
- 'SiteOrigin_Widget_Image_Widget',
298
- 'SiteOrigin_Panels_Widgets_Layout',
299
- ) )
300
- ),
301
-
302
- // General localization messages
303
- 'loc' => array(
304
- 'missing_widget' => array(
305
- 'title' => __( 'Missing Widget', 'siteorigin-panels' ),
306
- 'description' => __( "Page Builder doesn't know about this widget.", 'siteorigin-panels' ),
307
- ),
308
- 'time' => array(
309
- // TRANSLATORS: Number of seconds since
310
- 'seconds' => __( '%d seconds', 'siteorigin-panels' ),
311
- // TRANSLATORS: Number of minutes since
312
- 'minutes' => __( '%d minutes', 'siteorigin-panels' ),
313
- // TRANSLATORS: Number of hours since
314
- 'hours' => __( '%d hours', 'siteorigin-panels' ),
315
-
316
- // TRANSLATORS: A single second since
317
- 'second' => __( '%d second', 'siteorigin-panels' ),
318
- // TRANSLATORS: A single minute since
319
- 'minute' => __( '%d minute', 'siteorigin-panels' ),
320
- // TRANSLATORS: A single hour since
321
- 'hour' => __( '%d hour', 'siteorigin-panels' ),
322
-
323
- // TRANSLATORS: Time ago - eg. "1 minute before".
324
- 'ago' => __( '%s before', 'siteorigin-panels' ),
325
- 'now' => __( 'Now', 'siteorigin-panels' ),
326
- ),
327
- 'history' => array(
328
- // History messages
329
- 'current' => __( 'Current', 'siteorigin-panels' ),
330
- 'revert' => __( 'Original', 'siteorigin-panels' ),
331
- 'restore' => __( 'Version restored', 'siteorigin-panels' ),
332
- 'back_to_editor' => __( 'Converted to editor', 'siteorigin-panels' ),
333
-
334
- // Widgets
335
- // TRANSLATORS: Message displayed in the history when a widget is deleted
336
- 'widget_deleted' => __( 'Widget deleted', 'siteorigin-panels' ),
337
- // TRANSLATORS: Message displayed in the history when a widget is added
338
- 'widget_added' => __( 'Widget added', 'siteorigin-panels' ),
339
- // TRANSLATORS: Message displayed in the history when a widget is edited
340
- 'widget_edited' => __( 'Widget edited', 'siteorigin-panels' ),
341
- // TRANSLATORS: Message displayed in the history when a widget is duplicated
342
- 'widget_duplicated' => __( 'Widget duplicated', 'siteorigin-panels' ),
343
- // TRANSLATORS: Message displayed in the history when a widget position is changed
344
- 'widget_moved' => __( 'Widget moved', 'siteorigin-panels' ),
345
-
346
- // Rows
347
- // TRANSLATORS: Message displayed in the history when a row is deleted
348
- 'row_deleted' => __( 'Row deleted', 'siteorigin-panels' ),
349
- // TRANSLATORS: Message displayed in the history when a row is added
350
- 'row_added' => __( 'Row added', 'siteorigin-panels' ),
351
- // TRANSLATORS: Message displayed in the history when a row is edited
352
- 'row_edited' => __( 'Row edited', 'siteorigin-panels' ),
353
- // TRANSLATORS: Message displayed in the history when a row position is changed
354
- 'row_moved' => __( 'Row moved', 'siteorigin-panels' ),
355
- // TRANSLATORS: Message displayed in the history when a row is duplicated
356
- 'row_duplicated' => __( 'Row duplicated', 'siteorigin-panels' ),
357
- // TRANSLATORS: Message displayed in the history when a row is pasted
358
- 'row_pasted' => __( 'Row pasted', 'siteorigin-panels' ),
359
-
360
- // Cells
361
- 'cell_resized' => __( 'Cell resized', 'siteorigin-panels' ),
362
-
363
- // Prebuilt
364
- 'prebuilt_loaded' => __( 'Prebuilt layout loaded', 'siteorigin-panels' ),
365
- ),
366
-
367
- // general localization
368
- 'prebuilt_loading' => __( 'Loading prebuilt layout', 'siteorigin-panels' ),
369
- 'confirm_use_builder' => __( "Would you like to copy this editor's existing content to Page Builder?", 'siteorigin-panels' ),
370
- 'confirm_stop_builder' => __( "Would you like to clear your Page Builder content and revert to using the standard visual editor?", 'siteorigin-panels' ),
371
- // TRANSLATORS: This is the title for a widget called "Layout Builder"
372
- 'layout_widget' => __( 'Layout Builder Widget', 'siteorigin-panels' ),
373
- // TRANSLATORS: A standard confirmation message
374
- 'dropdown_confirm' => __( 'Are you sure?', 'siteorigin-panels' ),
375
- // TRANSLATORS: When a layout file is ready to be inserted. %s is the filename.
376
- 'ready_to_insert' => __( '%s is ready to insert.', 'siteorigin-panels' ),
377
-
378
- // Everything for the contextual menu
379
- 'contextual' => array(
380
- 'add_widget_below' => __( 'Add Widget Below', 'siteorigin-panels' ),
381
- 'add_widget_cell' => __( 'Add Widget to Cell', 'siteorigin-panels' ),
382
- 'search_widgets' => __( 'Search Widgets', 'siteorigin-panels' ),
383
-
384
- 'add_row' => __( 'Add Row', 'siteorigin-panels' ),
385
- 'column' => __( 'Column', 'siteorigin-panels' ),
386
-
387
- 'cell_actions' => __( 'Cell Actions', 'siteorigin-panels' ),
388
- 'cell_paste_widget' => __( 'Paste Widget', 'siteorigin-panels' ),
389
-
390
- 'widget_actions' => __( 'Widget Actions', 'siteorigin-panels' ),
391
- 'widget_edit' => __( 'Edit Widget', 'siteorigin-panels' ),
392
- 'widget_duplicate' => __( 'Duplicate Widget', 'siteorigin-panels' ),
393
- 'widget_delete' => __( 'Delete Widget', 'siteorigin-panels' ),
394
- 'widget_copy' => __( 'Copy Widget', 'siteorigin-panels' ),
395
- 'widget_paste' => __( 'Paste Widget Below', 'siteorigin-panels' ),
396
-
397
- 'row_actions' => __( 'Row Actions', 'siteorigin-panels' ),
398
- 'row_edit' => __( 'Edit Row', 'siteorigin-panels' ),
399
- 'row_duplicate' => __( 'Duplicate Row', 'siteorigin-panels' ),
400
- 'row_delete' => __( 'Delete Row', 'siteorigin-panels' ),
401
- 'row_copy' => __( 'Copy Row', 'siteorigin-panels' ),
402
- 'row_paste' => __( 'Paste Row', 'siteorigin-panels' ),
403
- ),
404
- 'draft' => __( 'Draft', 'siteorigin-panels' ),
405
- 'untitled' => __( 'Untitled', 'siteorigin-panels' ),
406
- 'row' => array(
407
- 'add' => __( 'New Row', 'siteorigin-panels' ),
408
- 'edit' => __( 'Row', 'siteorigin-panels' ),
409
- ),
410
- 'welcomeMessage' => array(
411
- 'addingDisabled' => __( 'Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements.', 'siteorigin-panels' ),
412
- 'oneEnabled' => __( 'Add a {{%= items[0] %}} to get started.', 'siteorigin-panels' ),
413
- 'twoEnabled' => __( 'Add a {{%= items[0] %}} or {{%= items[1] %}} to get started.', 'siteorigin-panels' ),
414
- 'threeEnabled' => __( 'Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started.', 'siteorigin-panels' ),
415
- 'addWidgetButton' => "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
416
- 'addRowButton' => "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
417
- 'addPrebuiltButton' => "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
418
- 'docsMessage' => sprintf(
419
- __( 'Read our %s if you need help.', 'siteorigin-panels' ),
420
- "<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
421
- ),
422
- ),
423
- ),
424
- 'plupload' => array(
425
- 'max_file_size' => wp_max_upload_size() . 'b',
426
- 'url' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
427
- 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
428
- 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
429
- 'filter_title' => __( 'Page Builder layouts', 'siteorigin-panels' ),
430
- 'error_message' => __( 'Error uploading or importing file.', 'siteorigin-panels' ),
431
- ),
432
- 'wpColorPickerOptions' => apply_filters( 'siteorigin_panels_wpcolorpicker_options', array() ),
433
- 'prebuiltDefaultScreenshot' => siteorigin_panels_url( 'css/images/prebuilt-default.png' ),
434
- 'loadOnAttach' => siteorigin_panels_setting( 'load-on-attach' ),
435
- 'siteoriginWidgetRegex' => str_replace( '*+', '*', get_shortcode_regex( array( 'siteorigin_widget' ) ) ),
436
- ) );
437
-
438
- $js_widgets = array();
439
- if ( $screen->base != 'widgets' ) {
440
- // Render all the widget forms. A lot of widgets use this as a chance to enqueue their scripts
441
- $original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; // Make sure widgets don't change the global post.
442
- global $wp_widget_factory;
443
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
444
- ob_start();
445
- $return = $widget_obj->form( array() );
446
- // These are the new widgets in WP 4.8 which are largely JS based. They only enqueue their own
447
- // scripts on the 'widgets' screen.
448
- if ( method_exists( $widget_obj, 'enqueue_admin_scripts' ) ) {
449
- $widget_obj->enqueue_admin_scripts();
450
- }
451
- do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, array() ) );
452
- ob_end_clean();
453
-
454
- // Need to render templates for new WP 4.8 widgets when not on the 'widgets' screen or in the customizer.
455
- if ( $this->is_js_widget( $widget_obj ) ) {
456
- $js_widgets[] = $widget_obj;
457
- }
458
- }
459
- $GLOBALS['post'] = $original_post;
460
- }
461
-
462
- // This gives panels a chance to enqueue scripts too, without having to check the screen ID.
463
- if ( $screen->base != 'widgets' && $screen->base != 'customize' ) {
464
- foreach ( $js_widgets as $js_widget ) {
465
- $js_widget->render_control_template_scripts();
466
- }
467
- do_action( 'siteorigin_panel_enqueue_admin_scripts' );
468
- do_action( 'sidebar_admin_setup' );
469
- }
470
- }
471
- }
472
-
473
- /**
474
- * Enqueue the admin panel styles
475
- *
476
- * @param string $prefix
477
- * @param bool $force Should we force the enqueue
478
- *
479
- * @action admin_print_styles-post-new.php
480
- * @action admin_print_styles-post.php
481
- */
482
- function enqueue_admin_styles( $prefix = '', $force = false ) {
483
- if ( $force || self::is_admin() ) {
484
- wp_enqueue_style(
485
- 'so-panels-admin',
486
- siteorigin_panels_url( 'css/admin.css' ),
487
- array( 'wp-color-picker' ),
488
- SITEORIGIN_PANELS_VERSION
489
- );
490
- do_action( 'siteorigin_panel_enqueue_admin_styles' );
491
- }
492
- }
493
-
494
- /**
495
- * Add a help tab to pages that include a Page Builder interface.
496
- *
497
- * @param $prefix
498
- */
499
- function add_help_tab( $prefix ) {
500
- $screen = get_current_screen();
501
- if (
502
- ( $screen->base == 'post' && ( in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) || $screen->id == '' ) )
503
- || ( $screen->id == 'appearance_page_so_panels_home_page' )
504
- ) {
505
- $screen->add_help_tab( array(
506
- 'id' => 'panels-help-tab', //unique id for the tab
507
- 'title' => __( 'Page Builder', 'siteorigin-panels' ), //unique visible title for the tab
508
- 'callback' => array( $this, 'help_tab_content' )
509
- ) );
510
- }
511
- }
512
-
513
- /**
514
- * Display the content for the help tab.
515
- */
516
- function help_tab_content() {
517
- include plugin_dir_path( __FILE__ ) . '../tpl/help.php';
518
- }
519
-
520
- /**
521
- * Get the Page Builder data for the current admin page.
522
- *
523
- * @return array
524
- */
525
- function get_current_admin_panels_data() {
526
- $screen = get_current_screen();
527
-
528
- // Localize the panels with the panels data
529
- if ( $screen->base == 'appearance_page_so_panels_home_page' ) {
530
- $home_page_id = get_option( 'page_on_front' );
531
- if ( empty( $home_page_id ) ) {
532
- $home_page_id = get_option( 'siteorigin_panels_home_page_id' );
533
- }
534
-
535
- $panels_data = ! empty( $home_page_id ) ? get_post_meta( $home_page_id, 'panels_data', true ) : null;
536
-
537
- if ( is_null( $panels_data ) ) {
538
- // Load the default layout
539
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
540
-
541
- $home_name = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
542
- $panels_data = ! empty( $layouts[ $home_name ] ) ? $layouts[ $home_name ] : current( $layouts );
543
- } elseif ( empty( $panels_data ) ) {
544
- // The current page_on_front isn't using page builder
545
- return false;
546
- }
547
-
548
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, 'home' );
549
- } else {
550
- global $post;
551
- $panels_data = get_post_meta( $post->ID, 'panels_data', true );
552
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post->ID );
553
- }
554
-
555
- if ( empty( $panels_data ) ) {
556
- $panels_data = array();
557
- }
558
-
559
- return $panels_data;
560
- }
561
-
562
- /**
563
- * Save home page
564
- */
565
- function save_home_page() {
566
- if ( ! isset( $_POST['_sopanels_home_nonce'] ) || ! wp_verify_nonce( $_POST['_sopanels_home_nonce'], 'save' ) ) {
567
- return;
568
- }
569
- if ( ! current_user_can( 'edit_theme_options' ) ) {
570
- return;
571
- }
572
- if ( ! isset( $_POST['panels_data'] ) ) {
573
- return;
574
- }
575
-
576
- // Check that the home page ID is set and the home page exists
577
- $page_id = get_option( 'page_on_front' );
578
- if ( empty( $page_id ) ) {
579
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
580
- }
581
-
582
- $post_content = wp_unslash( $_POST['post_content'] );
583
-
584
- if ( ! $page_id || get_post_meta( $page_id, 'panels_data', true ) == '' ) {
585
- // Lets create a new page
586
- $page_id = wp_insert_post( array(
587
- // TRANSLATORS: This is the default name given to a user's home page
588
- 'post_title' => __( 'Home Page', 'siteorigin-panels' ),
589
- 'post_status' => ! empty( $_POST['siteorigin_panels_home_enabled'] ) ? 'publish' : 'draft',
590
- 'post_type' => 'page',
591
- 'post_content' => $post_content,
592
- 'comment_status' => 'closed',
593
- ) );
594
- update_option( 'page_on_front', $page_id );
595
- update_option( 'siteorigin_panels_home_page_id', $page_id );
596
-
597
- // Action triggered when creating a new home page through the custom home page interface
598
- do_action( 'siteorigin_panels_create_home_page', $page_id );
599
- } else {
600
- // `wp_insert_post` does it's own sanitization, but it seems `wp_update_post` doesn't.
601
- $post_content = sanitize_post_field( 'post_content', $post_content, $page_id, 'db' );
602
-
603
- // Update the post with changed content to save revision if necessary.
604
- wp_update_post( array( 'ID' => $page_id, 'post_content' => $post_content ) );
605
- }
606
-
607
- $page = get_post( $page_id );
608
-
609
- // Save the updated page data
610
- $old_panels_data = get_post_meta( $page_id, 'panels_data', true );
611
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
612
- $panels_data['widgets'] = $this->process_raw_widgets(
613
- $panels_data['widgets'],
614
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
615
- false
616
- );
617
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
618
- $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $page, $page_id );
619
-
620
- update_post_meta( $page_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
621
-
622
- $template = get_post_meta( $page_id, '_wp_page_template', true );
623
- $home_template = siteorigin_panels_setting( 'home-template' );
624
- if ( ( $template == '' || $template == 'default' ) && ! empty( $home_template ) ) {
625
- // Set the home page template
626
- update_post_meta( $page_id, '_wp_page_template', $home_template );
627
- }
628
-
629
- if ( ! empty( $_POST['siteorigin_panels_home_enabled'] ) ) {
630
- update_option( 'show_on_front', 'page' );
631
- update_option( 'page_on_front', $page_id );
632
- update_option( 'siteorigin_panels_home_page_id', $page_id );
633
- wp_publish_post( $page_id );
634
- } else {
635
- // We're disabling this home page
636
- update_option( 'show_on_front', 'posts' );
637
-
638
- // Change the post status to draft
639
- $post = get_post( $page_id );
640
- if ( $post->post_status != 'draft' ) {
641
- global $wpdb;
642
-
643
- $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $post->ID ) );
644
- clean_post_cache( $post->ID );
645
-
646
- $old_status = $post->post_status;
647
- $post->post_status = 'draft';
648
- wp_transition_post_status( 'draft', $old_status, $post );
649
-
650
- do_action( 'edit_post', $post->ID, $post );
651
- do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
652
- do_action( 'save_post', $post->ID, $post, true );
653
- do_action( 'wp_insert_post', $post->ID, $post, true );
654
- }
655
- }
656
- }
657
-
658
- /**
659
- * After the theme is switched, change the template on the home page if the theme supports home page functionality.
660
- */
661
- function update_home_on_theme_change() {
662
- $page_id = get_option( 'page_on_front' );
663
- if ( empty( $page_id ) ) {
664
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
665
- }
666
-
667
- if ( siteorigin_panels_setting( 'home-page' ) && siteorigin_panels_setting( 'home-template' ) && $page_id && get_post_meta( $page_id, 'panels_data', true ) !== '' ) {
668
- // Lets update the home page to use the home template that this theme supports
669
- update_post_meta( $page_id, '_wp_page_template', siteorigin_panels_setting( 'home-template' ) );
670
- }
671
- }
672
-
673
- /**
674
- * @return array|mixed|void
675
- */
676
- function get_widgets() {
677
- global $wp_widget_factory;
678
- $widgets = array();
679
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
680
- $widgets[ $class ] = array(
681
- 'class' => $class,
682
- 'title' => ! empty( $widget_obj->name ) ? $widget_obj->name : __( 'Untitled Widget', 'siteorigin-panels' ),
683
- 'description' => ! empty( $widget_obj->widget_options['description'] ) ? $widget_obj->widget_options['description'] : '',
684
- 'installed' => true,
685
- 'groups' => array(),
686
- );
687
-
688
- // Get Page Builder specific widget options
689
- if ( isset( $widget_obj->widget_options['panels_title'] ) ) {
690
- $widgets[ $class ]['panels_title'] = $widget_obj->widget_options['panels_title'];
691
- }
692
- if ( isset( $widget_obj->widget_options['panels_groups'] ) ) {
693
- $widgets[ $class ]['groups'] = $widget_obj->widget_options['panels_groups'];
694
- }
695
- if ( isset( $widget_obj->widget_options['panels_icon'] ) ) {
696
- $widgets[ $class ]['icon'] = $widget_obj->widget_options['panels_icon'];
697
- }
698
-
699
- }
700
-
701
- // Other plugins can manipulate the list of widgets. Possibly to add recommended widgets
702
- $widgets = apply_filters( 'siteorigin_panels_widgets', $widgets );
703
-
704
- // Sort the widgets alphabetically
705
- uasort( $widgets, array( $this, 'widgets_sorter' ) );
706
-
707
- return $widgets;
708
- }
709
-
710
- /**
711
- * Sorts widgets for get_widgets function by title
712
- *
713
- * @param $a
714
- * @param $b
715
- *
716
- * @return int
717
- */
718
- function widgets_sorter( $a, $b ) {
719
- if ( empty( $a['title'] ) ) {
720
- return - 1;
721
- }
722
- if ( empty( $b['title'] ) ) {
723
- return 1;
724
- }
725
-
726
- return $a['title'] > $b['title'] ? 1 : - 1;
727
- }
728
-
729
- /**
730
- * Process raw widgets that have come from the Page Builder front end.
731
- *
732
- * @param array $widgets An array of widgets from panels_data.
733
- * @param array $old_widgets
734
- * @param bool $escape_classes Should the class names be escaped.
735
- * @param bool $force
736
- *
737
- * @return array
738
- */
739
- function process_raw_widgets( $widgets, $old_widgets = array(), $escape_classes = false, $force = false ) {
740
- if ( empty( $widgets ) || ! is_array( $widgets ) ) {
741
- return array();
742
- }
743
-
744
- global $wp_widget_factory;
745
-
746
- $old_widgets_by_id = array();
747
- if( ! empty( $old_widgets ) ) {
748
- foreach( $old_widgets as $widget ) {
749
- if( ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) ) {
750
- $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] = $widget;
751
- unset( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ][ 'panels_info' ] );
752
- }
753
- }
754
- }
755
-
756
- foreach( $widgets as $i => & $widget ) {
757
- if ( ! is_array( $widget ) ) {
758
- continue;
759
- }
760
-
761
- if ( is_array( $widget ) ) {
762
- $info = (array) ( is_array( $widget['panels_info'] ) ? $widget['panels_info'] : $widget['info'] );
763
- } else {
764
- $info = array();
765
- }
766
- unset( $widget['info'] );
767
-
768
- $info[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $info[ 'class' ] );
769
-
770
- if ( ! empty( $info['raw'] ) || $force ) {
771
- if ( isset( $wp_widget_factory->widgets[ $info['class'] ] ) && method_exists( $info['class'], 'update' ) ) {
772
-
773
- if(
774
- ! empty( $old_widgets_by_id ) &&
775
- ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) &&
776
- ! empty( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] )
777
- ){
778
- $old_widget = $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ];
779
- }
780
- else {
781
- $old_widget = $widget;
782
- }
783
-
784
- /** @var WP_Widget $the_widget */
785
- $the_widget = $wp_widget_factory->widgets[ $info['class'] ];
786
- $instance = $the_widget->update( $widget, $old_widget );
787
- $instance = apply_filters( 'widget_update_callback', $instance, $widget, $old_widget, $the_widget );
788
-
789
- $widget = $instance;
790
- unset( $info['raw'] );
791
- }
792
- }
793
-
794
- if( $escape_classes ) {
795
- // Escaping for namespaced widgets
796
- $info[ 'class' ] = preg_replace( '/\\\\+/', '\\\\\\\\', $info['class'] );
797
- }
798
- $widget['panels_info'] = $info;
799
- }
800
-
801
- return $widgets;
802
- }
803
-
804
- /**
805
- * Add all the footer JS templates.
806
- */
807
- function js_templates() {
808
- include plugin_dir_path( __FILE__ ) . '../tpl/js-templates.php';
809
- }
810
-
811
- /**
812
- * Render a widget form with all the Page Builder specific fields
813
- *
814
- * @param string $widget The class of the widget
815
- * @param array $instance Widget values
816
- * @param bool $raw
817
- * @param string $widget_number
818
- *
819
- * @return mixed|string The form
820
- */
821
- function render_form( $widget, $instance = array(), $raw = false, $widget_number = '{$id}' ) {
822
- global $wp_widget_factory;
823
-
824
- // This is a chance for plugins to replace missing widgets
825
- $the_widget = ! empty( $wp_widget_factory->widgets[ $widget ] ) ? $wp_widget_factory->widgets[ $widget ] : false;
826
- $the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget );
827
-
828
- if ( empty( $the_widget ) || ! is_a( $the_widget, 'WP_Widget' ) ) {
829
- $widgets = $this->get_widgets();
830
-
831
- if ( ! empty( $widgets[ $widget ] ) && ! empty( $widgets[ $widget ]['plugin'] ) ) {
832
- // We know about this widget, show a form about installing it.
833
- $install_url = siteorigin_panels_plugin_activation_install_url( $widgets[ $widget ]['plugin']['slug'], $widgets[ $widget ]['plugin']['name'] );
834
- $form =
835
- '<div class="panels-missing-widget-form">' .
836
- '<p>' .
837
- preg_replace(
838
- array(
839
- '/1\{ *(.*?) *\}/',
840
- '/2\{ *(.*?) *\}/',
841
- ),
842
- array(
843
- '<a href="' . $install_url . '" target="_blank" rel="noopener noreferrer">$1</a>',
844
- '<strong>$1</strong>'
845
- ),
846
- sprintf(
847
- __( 'You need to install 1{%1$s} to use the widget 2{%2$s}.', 'siteorigin-panels' ),
848
- $widgets[ $widget ]['plugin']['name'],
849
- $widget
850
- )
851
- ) .
852
- '</p>' .
853
- '<p>' . __( "Save and reload this page to start using the widget after you've installed it.", 'siteorigin-panels' ) . '</p>' .
854
- '</div>';
855
- } else {
856
- // This widget is missing, so show a missing widgets form.
857
- $form =
858
- '<div class="panels-missing-widget-form"><p>' .
859
- preg_replace(
860
- array(
861
- '/1\{ *(.*?) *\}/',
862
- '/2\{ *(.*?) *\}/',
863
- ),
864
- array(
865
- '<strong>$1</strong>',
866
- '<a href="https://siteorigin.com/thread/" target="_blank" rel="noopener noreferrer">$1</a>'
867
- ),
868
- sprintf(
869
- __( 'The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help.', 'siteorigin-panels' ),
870
- esc_html( $widget )
871
- )
872
- ) .
873
- '</p></div>';
874
- }
875
-
876
- // Allow other themes and plugins to change the missing widget form
877
- return apply_filters( 'siteorigin_panels_missing_widget_form', $form, $widget, $instance );
878
- }
879
-
880
- if ( $raw ) {
881
- $instance = $the_widget->update( $instance, $instance );
882
- }
883
-
884
- $the_widget->id = 'temp';
885
- $the_widget->number = $widget_number;
886
-
887
- ob_start();
888
- if ( $this->is_js_widget( $the_widget ) ) {
889
- ?><div class="widget-content"><?php
890
- }
891
- $return = $the_widget->form( $instance );
892
- do_action_ref_array( 'in_widget_form', array( &$the_widget, &$return, $instance ) );
893
- if ( $this->is_js_widget( $the_widget ) ) {
894
- ?>
895
- </div>
896
- <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $the_widget->id_base ); ?>" />
897
- <?php
898
- }
899
- $form = ob_get_clean();
900
-
901
- // Convert the widget field naming into ones that Page Builder uses
902
- $exp = preg_quote( $the_widget->get_field_name( '____' ) );
903
- $exp = str_replace( '____', '(.*?)', $exp );
904
- $form = preg_replace( '/' . $exp . '/', 'widgets[' . preg_replace( '/\$(\d)/', '\\\$$1', $widget_number ) . '][$1]', $form );
905
-
906
- $form = apply_filters( 'siteorigin_panels_widget_form', $form, $widget, $instance );
907
-
908
- // Add all the information fields
909
- return $form;
910
- }
911
-
912
- function is_js_widget( $widget ) {
913
- $js_widgets = array(
914
- 'WP_Widget_Custom_HTML',
915
- 'WP_Widget_Media_Audio',
916
- 'WP_Widget_Media_Gallery',
917
- 'WP_Widget_Media_Image',
918
- 'WP_Widget_Media_Video',
919
- 'WP_Widget_Text',
920
- );
921
-
922
- $is_js_widget = in_array( get_class( $widget ), $js_widgets ) &&
923
- // Need to check this for `WP_Widget_Text` which was not a JS widget before 4.8
924
- method_exists( $widget, 'render_control_template_scripts' );
925
-
926
- return $is_js_widget;
927
- }
928
-
929
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
930
- // ADMIN AJAX ACTIONS
931
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
932
-
933
- /**
934
- * Get builder content based on the submitted panels_data.
935
- */
936
- function action_builder_content() {
937
- header( 'content-type: text/html' );
938
-
939
- if ( ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
940
- wp_die();
941
- }
942
-
943
- if ( empty( $_POST['post_id'] ) || empty( $_POST['panels_data'] ) ) {
944
- echo '';
945
- wp_die();
946
- }
947
-
948
- // echo the content
949
- $old_panels_data = get_post_meta( $_POST['post_id'], 'panels_data', true );
950
- $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
951
- $panels_data['widgets'] = $this->process_raw_widgets(
952
- $panels_data['widgets'],
953
- ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
954
- false
955
- );
956
- $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
957
-
958
- // Create a version of the builder data for post content
959
- SiteOrigin_Panels_Post_Content_Filters::add_filters();
960
- $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
961
- echo SiteOrigin_Panels::renderer()->render( intval( $_POST['post_id'] ), false, $panels_data );
962
- SiteOrigin_Panels_Post_Content_Filters::remove_filters();
963
- unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
964
-
965
- wp_die();
966
- }
967
-
968
- /**
969
- * Display a widget form with the provided data
970
- */
971
- function action_widget_form() {
972
- if ( empty( $_REQUEST['widget'] ) ) {
973
- wp_die();
974
- }
975
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
976
- wp_die();
977
- }
978
-
979
- $request = array_map( 'stripslashes_deep', $_REQUEST );
980
-
981
- $widget_class = $request['widget'];
982
- $widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
983
- $instance = ! empty( $request['instance'] ) ? json_decode( $request['instance'], true ) : array();
984
-
985
- $form = $this->render_form( $widget_class, $instance, $_REQUEST['raw'] == 'true' );
986
- $form = apply_filters( 'siteorigin_panels_ajax_widget_form', $form, $widget_class, $instance );
987
-
988
- echo $form;
989
- wp_die();
990
- }
991
-
992
- /**
993
- * Preview in the live editor when there is no public view of the item
994
- */
995
- function action_live_editor_preview() {
996
- if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'live-editor-preview' ) ) {
997
- wp_die();
998
- }
999
-
1000
- include plugin_dir_path( __FILE__ ) . '../tpl/live-editor-preview.php';
1001
-
1002
- exit();
1003
- }
1004
-
1005
- /**
1006
- * Add a column that indicates if a column is powered by Page Builder
1007
- *
1008
- * @param $columns
1009
- *
1010
- * @return array
1011
- */
1012
- function add_custom_column( $columns ){
1013
- $index = array_search( 'comments', array_keys( $columns ) );
1014
-
1015
- if( empty( $index ) ) {
1016
- $columns = array_merge(
1017
- $columns,
1018
- array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) )
1019
- );
1020
- }
1021
- else {
1022
- $columns = array_slice( $columns, 0, $index, true ) +
1023
- array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) ) +
1024
- array_slice( $columns, $index, count( $columns ) - 1, true );
1025
- }
1026
-
1027
- return $columns;
1028
- }
1029
-
1030
- function display_custom_column( $column, $post_id ){
1031
- if( $column != 'panels' ) return;
1032
-
1033
- $panels_data = get_post_meta( $post_id, 'panels_data', true );
1034
- if( ! empty( $panels_data['widgets'] ) ) {
1035
- printf( __( '%s Widgets', 'siteorigin-panels' ), count( $panels_data['widgets'] ) );
1036
- }
1037
- else {
1038
- echo '—';
1039
- }
1040
- }
1041
-
1042
- public function footer_column_css(){
1043
- if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
1044
- $screen = get_current_screen();
1045
- $post_types = siteorigin_panels_setting( 'post-types' );
1046
-
1047
- if(
1048
- $screen->base == 'edit' &&
1049
- is_array( $post_types ) &&
1050
- in_array( $screen->post_type, $post_types )
1051
- ){
1052
- ?><style type="text/css">.column-panels{ width: 10% }</style><?php
1053
- }
1054
- }
1055
- }
1056
-
1057
- /**
1058
- * Add double slashes to strings
1059
- *
1060
- * @param $value
1061
- *
1062
- * @return string
1063
- */
1064
- public static function double_slash_string( $value ){
1065
- return is_string( $value ) ? addcslashes( $value, '\\' ) : $value;
1066
- }
1067
-
1068
- public function get_layout_directories(){
1069
-
1070
- }
1071
-
1072
- /**
1073
- * Add all the courses to the learning dialog
1074
- *
1075
- * @param $lessons
1076
- *
1077
- * @return mixed
1078
- */
1079
- public function filter_learn_lessons( $lessons ) {
1080
- $lessons['page-builder-tips'] = array(
1081
- 'title' => __( '12 Page Builder Tips', 'siteorigin-panels' ),
1082
- 'video' => '212380146',
1083
- 'poster' => siteorigin_panels_url( 'posters/page-builder-tips.svg' ),
1084
- 'description' => __( "Sign up to our newsletter and we'll send you this free Page Builder video course.", 'siteorigin-panels' ) . ' ' .
1085
- __( "12 tips that'll help you get the most out of Page Builder.", 'siteorigin-panels' ) . ' ' .
1086
- __( "Watch the video to find out more, then sign up below to get started.", 'siteorigin-panels' ),
1087
- 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1088
- );
1089
-
1090
- $lessons['page-builder-animations'] = array(
1091
- 'title' => __( 'Free Page Builder Addons', 'siteorigin-panels' ),
1092
- 'video' => '212380210',
1093
- 'poster' => siteorigin_panels_url( 'posters/addons.svg' ),
1094
- 'description' => __( "The free animations addon allows you to add beautiful animations to Page Builder elements.", 'siteorigin-panels' ) . ' ' .
1095
- __( "Sign up to our newsletter and we'll send you the addon as a free gift.", 'siteorigin-panels' ) . ' ' .
1096
- __( "Plus, we'll send you even more powerful addons, for as long as you're subscribed.", 'siteorigin-panels' ),
1097
- 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1098
- );
1099
-
1100
- return $lessons;
1101
- }
1102
-
1103
- /**
1104
- * Filter the translation strings for SiteOrigin learning dialogs
1105
- *
1106
- * @param $strings
1107
- *
1108
- * @return array
1109
- */
1110
- public function filter_learn_strings( $strings ){
1111
- $strings = array(
1112
- 'watch_video' => __( 'Watch Intro Video', 'siteorigin-panels' ),
1113
- 'loaded_from_vimeo' => __( 'Loaded from Vimeo Servers', 'siteorigin-panels' ),
1114
- 'valid_email' => __( 'Please enter a valid email address.', 'siteorigin-panels' ),
1115
-
1116
- 'your_name' => __( 'Your Name', 'siteorigin-panels' ),
1117
- 'your_email' => __( 'Your Email', 'siteorigin-panels' ),
1118
- 'sign_up' => __( 'Sign Up', 'siteorigin-panels' ),
1119
- 'close' => __( 'Close', 'siteorigin-panels' ),
1120
- );
1121
- return $strings;
1122
- }
1123
-
1124
- /**
1125
- * Display links for various SiteOrigin addons
1126
- */
1127
- public static function display_footer_premium_link(){
1128
- $links = array(
1129
- array(
1130
- 'text' => __('Get a lightbox addon for SiteOrigin widgets', 'siteorigin-panels'),
1131
- 'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
1132
- ),
1133
- array(
1134
- 'text' => __('Get the row, cell and widget animations addon', 'siteorigin-panels'),
1135
- 'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
1136
- ),
1137
- array(
1138
- 'text' => __('Get premium email support for SiteOrigin Page Builder', 'siteorigin-panels'),
1139
- 'url' => SiteOrigin_Panels::premium_url()
1140
- ),
1141
- );
1142
- $link = $links[array_rand($links)];
1143
-
1144
- ?>
1145
- <a href="<?php echo esc_url( $link['url'] ) ?>" target="_blank" rel='noopener noreferrer'>
1146
- <?php echo esc_html( $link['text'] ) ?>.
1147
- </a>
1148
- <?php
1149
- }
1150
-
1151
- /**
1152
- * Disable the Gutenberg editor for existing PB posts.
1153
- *
1154
- * @param $can_edit
1155
- * @param $post_type
1156
- *
1157
- * @return bool
1158
- */
1159
- public function disable_gutenberg_for_panels_posts( $can_edit, $post_type ) {
1160
- $screen = get_current_screen();
1161
- $post_types = siteorigin_panels_setting( 'post-types' );
1162
- $panels_data = $screen->base == 'post' ? $this->get_current_admin_panels_data() : array();
1163
-
1164
- $is_panels_page = in_array( $post_type, $post_types ) && ! empty( $panels_data );
1165
-
1166
- return ! $is_panels_page && $can_edit;
1167
- }
1168
-
1169
- /**
1170
- * Disable PB when we're in the Gutenberg editor.
1171
- *
1172
- * @param $wp_meta_boxes
1173
- *
1174
- * @return mixed
1175
- */
1176
- public function disable_panels_for_gutenberg_posts( $wp_meta_boxes ) {
1177
- foreach ( $wp_meta_boxes as &$locations ) {
1178
- foreach ( $locations as &$priorities ) {
1179
- foreach ( $priorities as &$boxes ) {
1180
- unset( $boxes['so-panels-panels'] );
1181
- unset( $boxes['siteorigin_page_settings'] );
1182
-
1183
- }
1184
- }
1185
- }
1186
- return $wp_meta_boxes;
1187
- }
1188
- }
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Panels_Admin
5
+ *
6
+ * Handles all the admin and database interactions.
7
+ */
8
+ class SiteOrigin_Panels_Admin {
9
+
10
+ /**
11
+ * @var bool Store that we're in the save post action, to prevent infinite loops
12
+ */
13
+ private $in_save_post;
14
+
15
+ function __construct() {
16
+
17
+ add_action( 'plugin_action_links_siteorigin-panels/siteorigin-panels.php', array(
18
+ $this,
19
+ 'plugin_action_links'
20
+ ) );
21
+
22
+ add_action( 'current_screen', array( $this, 'admin_init' ) );
23
+
24
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
25
+ add_action( 'admin_init', array( $this, 'save_home_page' ) );
26
+ add_action( 'save_post', array( $this, 'save_post' ) );
27
+
28
+ add_action( 'after_switch_theme', array( $this, 'update_home_on_theme_change' ) );
29
+
30
+ // Enqueuing admin scripts
31
+ add_action( 'admin_print_scripts-post-new.php', array( $this, 'enqueue_admin_scripts' ) );
32
+ add_action( 'admin_print_scripts-post.php', array( $this, 'enqueue_admin_scripts' ) );
33
+ add_action( 'admin_print_scripts-appearance_page_so_panels_home_page', array(
34
+ $this,
35
+ 'enqueue_admin_scripts'
36
+ ) );
37
+ add_action( 'admin_print_scripts-widgets.php', array( $this, 'enqueue_admin_scripts' ) );
38
+ add_action( 'admin_print_scripts-edit.php', array( $this, 'footer_column_css' ) );
39
+
40
+ // Enqueue the admin styles
41
+ add_action( 'admin_print_styles-post-new.php', array( $this, 'enqueue_admin_styles' ) );
42
+ add_action( 'admin_print_styles-post.php', array( $this, 'enqueue_admin_styles' ) );
43
+ add_action( 'admin_print_styles-appearance_page_so_panels_home_page', array( $this, 'enqueue_admin_styles' ) );
44
+ add_action( 'admin_print_styles-widgets.php', array( $this, 'enqueue_admin_styles' ) );
45
+
46
+ // The help tab
47
+ add_action( 'load-page.php', array( $this, 'add_help_tab' ), 12 );
48
+ add_action( 'load-post-new.php', array( $this, 'add_help_tab' ), 12 );
49
+ add_action( 'load-appearance_page_so_panels_home_page', array( $this, 'add_help_tab' ), 12 );
50
+
51
+ add_action( 'customize_controls_print_footer_scripts', array( $this, 'js_templates' ) );
52
+
53
+ // Register all the admin actions
54
+ add_action( 'wp_ajax_so_panels_builder_content', array( $this, 'action_builder_content' ) );
55
+ add_action( 'wp_ajax_so_panels_widget_form', array( $this, 'action_widget_form' ) );
56
+ add_action( 'wp_ajax_so_panels_live_editor_preview', array( $this, 'action_live_editor_preview' ) );
57
+
58
+ // Initialize the additional admin classes.
59
+ SiteOrigin_Panels_Admin_Widget_Dialog::single();
60
+ SiteOrigin_Panels_Admin_Widgets_Bundle::single();
61
+ SiteOrigin_Panels_Admin_Layouts::single();
62
+
63
+ $this->in_save_post = false;
64
+
65
+ add_filter( 'gutenberg_can_edit_post_type', array( $this, 'disable_gutenberg_for_panels_posts' ), 10, 2 );
66
+ add_filter( 'filter_gutenberg_meta_boxes', array( $this, 'disable_panels_for_gutenberg_posts' ) );
67
+ }
68
+
69
+ /**
70
+ * @return SiteOrigin_Panels_Admin
71
+ */
72
+ public static function single() {
73
+ static $single;
74
+ return empty( $single ) ? $single = new self() : $single;
75
+ }
76
+
77
+ /**
78
+ * Do some general admin initialization
79
+ */
80
+ public function admin_init(){
81
+ if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
82
+
83
+ // Add the custom columns
84
+ $post_types = siteorigin_panels_setting( 'post-types' );
85
+ if( ! empty( $post_types ) ) {
86
+ foreach( $post_types as $post_type ) {
87
+ add_filter( 'manage_' . $post_type . 's_columns' , array( $this, 'add_custom_column' ) );
88
+ add_action( 'manage_' . $post_type . 's_custom_column' , array( $this, 'display_custom_column' ), 10, 2 );
89
+ }
90
+ }
91
+ }
92
+
93
+ if( self::is_admin() ) {
94
+ // Setup everything for Page Builder learning as long as we're viewing a Page Builder page
95
+ SiteOrigin_Learn_Dialog::single();
96
+ add_filter( 'siteorigin_learn_lessons', array( $this, 'filter_learn_lessons' ) );
97
+ add_filter( 'siteorigin_learn_strings', array( $this, 'filter_learn_strings' ), 99 );
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Check if this is an admin page.
103
+ *
104
+ * @return mixed|void
105
+ */
106
+ static function is_admin() {
107
+ $screen = get_current_screen();
108
+ $is_panels_page = ( $screen->base == 'post' && in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) ) || $screen->base == 'appearance_page_so_panels_home_page' || $screen->base == 'widgets' || $screen->base == 'customize';
109
+
110
+ return apply_filters( 'siteorigin_panels_is_admin_page', $is_panels_page );
111
+ }
112
+
113
+ /**
114
+ * Add action links to the plugin list for Page Builder.
115
+ *
116
+ * @param $links
117
+ *
118
+ * @return array
119
+ */
120
+ function plugin_action_links( $links ) {
121
+ if( ! is_array( $links ) ) {
122
+ return $links;
123
+ }
124
+
125
+ unset( $links['edit'] );
126
+ $links[] = '<a href="http://siteorigin.com/threads/plugin-page-builder/">' . __( 'Support Forum', 'siteorigin-panels' ) . '</a>';
127
+ $links[] = '<a href="http://siteorigin.com/page-builder/#newsletter">' . __( 'Newsletter', 'siteorigin-panels' ) . '</a>';
128
+
129
+ if( SiteOrigin_Panels::display_premium_teaser() ) {
130
+ $links[] = '<a href="' . esc_url( SiteOrigin_Panels::premium_url() ) . '" style="color: #3db634" target="_blank" rel="noopener noreferrer">' . __('Addons', 'siteorigin-panels') . '</a>';
131
+ }
132
+
133
+ return $links;
134
+ }
135
+
136
+ /**
137
+ * Callback to register the Page Builder Metaboxes
138
+ */
139
+ function add_meta_boxes() {
140
+ foreach ( siteorigin_panels_setting( 'post-types' ) as $type ) {
141
+ add_meta_box(
142
+ 'so-panels-panels',
143
+ __( 'Page Builder', 'siteorigin-panels' ),
144
+ array( $this, 'render_meta_boxes' ),
145
+ ( string ) $type,
146
+ 'advanced',
147
+ 'high'
148
+ );
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Render a panel metabox.
154
+ *
155
+ * @param $post
156
+ */
157
+ function render_meta_boxes( $post ) {
158
+ $panels_data = $this->get_current_admin_panels_data();
159
+ include plugin_dir_path( __FILE__ ) . '../tpl/metabox-panels.php';
160
+ }
161
+
162
+ /**
163
+ * Save the panels data
164
+ *
165
+ * @param $post_id
166
+ * @param $post
167
+ *
168
+ * @action save_post
169
+ */
170
+ function save_post( $post_id ) {
171
+ // Check that everything is valid with this save.
172
+ if(
173
+ $this->in_save_post ||
174
+ ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ||
175
+ empty( $_POST['_sopanels_nonce'] ) ||
176
+ ! wp_verify_nonce( $_POST['_sopanels_nonce'], 'save' ) ||
177
+ ! current_user_can( 'edit_post', $post_id ) ||
178
+ ! isset( $_POST['panels_data'] )
179
+ ) {
180
+ return;
181
+ }
182
+ $this->in_save_post = true;
183
+ // Get post from db as it might have been changed and saved by other plugins.
184
+ $post = get_post( $post_id );
185
+ $old_panels_data = get_post_meta( $post_id, 'panels_data', true );
186
+ $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
187
+
188
+ $panels_data['widgets'] = $this->process_raw_widgets(
189
+ $panels_data['widgets'],
190
+ ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
191
+ false
192
+ );
193
+ $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
194
+ $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $post, $post_id );
195
+
196
+ if ( ! empty( $panels_data['widgets'] ) || ! empty( $panels_data['grids'] ) ) {
197
+ // Use `update_metadata` instead of `update_post_meta` to prevent saving to parent post when it's a revision, e.g. preview.
198
+ update_metadata( 'post', $post_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
199
+
200
+ if( siteorigin_panels_setting( 'copy-content' ) ) {
201
+ // Store a version of the HTML in post_content
202
+ SiteOrigin_Panels_Post_Content_Filters::add_filters();
203
+ $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
204
+ $post_content = SiteOrigin_Panels::renderer()->render( $post_id, false, $panels_data );
205
+ $post_css = SiteOrigin_Panels::renderer()->generate_css( $post_id, $panels_data );
206
+ SiteOrigin_Panels_Post_Content_Filters::remove_filters();
207
+ unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
208
+
209
+ // Update the post_content
210
+ $post->post_content = $post_content;
211
+ if( siteorigin_panels_setting( 'copy-styles' ) ) {
212
+ $post->post_content .= "\n\n";
213
+ $post->post_content .= '<style type="text/css" class="panels-style" data-panels-style-for-post="' . intval( $post_id ) . '">';
214
+ $post->post_content .= '@import url(' . SiteOrigin_Panels::front_css_url() . '); ';
215
+ $post->post_content .= $post_css;
216
+ $post->post_content .= '</style>';
217
+ }
218
+ wp_update_post( $post );
219
+ }
220
+
221
+ } else {
222
+ // There are no widgets or rows, so delete the panels data
223
+ delete_post_meta( $post_id, 'panels_data' );
224
+ }
225
+
226
+ $this->in_save_post = false;
227
+ }
228
+
229
+ /**
230
+ * Enqueue the panels admin scripts
231
+ *
232
+ * @param string $prefix
233
+ * @param bool $force Should we force the enqueues
234
+ *
235
+ * @action admin_print_scripts-post-new.php
236
+ * @action admin_print_scripts-post.php
237
+ * @action admin_print_scripts-appearance_page_so_panels_home_page
238
+ */
239
+ function enqueue_admin_scripts( $prefix = '', $force = false ) {
240
+ $screen = get_current_screen();
241
+ if ( $force || self::is_admin() ) {
242
+ // Media is required for row styles
243
+ wp_enqueue_media();
244
+ wp_enqueue_script(
245
+ 'so-panels-admin',
246
+ siteorigin_panels_url( 'js/siteorigin-panels' . SITEORIGIN_PANELS_VERSION_SUFFIX . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
247
+ array(
248
+ 'jquery',
249
+ 'jquery-ui-resizable',
250
+ 'jquery-ui-sortable',
251
+ 'jquery-ui-draggable',
252
+ 'underscore',
253
+ 'backbone',
254
+ 'plupload',
255
+ 'plupload-all'
256
+ ),
257
+ SITEORIGIN_PANELS_VERSION,
258
+ true
259
+ );
260
+ add_action( 'admin_footer', array( $this, 'js_templates' ) );
261
+
262
+ $widgets = $this->get_widgets();
263
+ $directory_enabled = get_user_meta( get_current_user_id(), 'so_panels_directory_enabled', true );
264
+
265
+ // This is the widget we'll use for default text
266
+ if( ! empty( $widgets[ 'SiteOrigin_Widget_Editor_Widget' ] ) ) $text_widget = 'SiteOrigin_Widget_Editor_Widget';
267
+ else if( ! empty( $widgets[ 'WP_Widget_Text' ] ) ) $text_widget = 'WP_Widget_Text';
268
+ else $text_widget = false;
269
+ $text_widget = apply_filters( 'siteorigin_panels_text_widget_class', $text_widget );
270
+
271
+ $user = wp_get_current_user();
272
+ wp_localize_script( 'so-panels-admin', 'panelsOptions', array(
273
+ 'user' => ! empty( $user ) ? $user->ID : 0,
274
+ 'ajaxurl' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
275
+ 'widgets' => $widgets,
276
+ 'text_widget' => $text_widget,
277
+ 'widget_dialog_tabs' => apply_filters( 'siteorigin_panels_widget_dialog_tabs', array(
278
+ 0 => array(
279
+ 'title' => __( 'All Widgets', 'siteorigin-panels' ),
280
+ 'filter' => array(
281
+ 'installed' => true,
282
+ 'groups' => ''
283
+ )
284
+ )
285
+ ) ),
286
+ 'row_layouts' => apply_filters( 'siteorigin_panels_row_layouts', array() ),
287
+ 'directory_enabled' => ! empty( $directory_enabled ),
288
+ 'copy_content' => siteorigin_panels_setting( 'copy-content' ),
289
+ 'cache' => array(),
290
+
291
+ // Settings for the contextual menu
292
+ 'contextual' => array(
293
+ // Developers can change which widgets are displayed by default using this filter
294
+ 'default_widgets' => apply_filters( 'siteorigin_panels_contextual_default_widgets', array(
295
+ 'SiteOrigin_Widget_Editor_Widget',
296
+ 'SiteOrigin_Widget_Button_Widget',
297
+ 'SiteOrigin_Widget_Image_Widget',
298
+ 'SiteOrigin_Panels_Widgets_Layout',
299
+ ) )
300
+ ),
301
+
302
+ // General localization messages
303
+ 'loc' => array(
304
+ 'missing_widget' => array(
305
+ 'title' => __( 'Missing Widget', 'siteorigin-panels' ),
306
+ 'description' => __( "Page Builder doesn't know about this widget.", 'siteorigin-panels' ),
307
+ ),
308
+ 'time' => array(
309
+ // TRANSLATORS: Number of seconds since
310
+ 'seconds' => __( '%d seconds', 'siteorigin-panels' ),
311
+ // TRANSLATORS: Number of minutes since
312
+ 'minutes' => __( '%d minutes', 'siteorigin-panels' ),
313
+ // TRANSLATORS: Number of hours since
314
+ 'hours' => __( '%d hours', 'siteorigin-panels' ),
315
+
316
+ // TRANSLATORS: A single second since
317
+ 'second' => __( '%d second', 'siteorigin-panels' ),
318
+ // TRANSLATORS: A single minute since
319
+ 'minute' => __( '%d minute', 'siteorigin-panels' ),
320
+ // TRANSLATORS: A single hour since
321
+ 'hour' => __( '%d hour', 'siteorigin-panels' ),
322
+
323
+ // TRANSLATORS: Time ago - eg. "1 minute before".
324
+ 'ago' => __( '%s before', 'siteorigin-panels' ),
325
+ 'now' => __( 'Now', 'siteorigin-panels' ),
326
+ ),
327
+ 'history' => array(
328
+ // History messages
329
+ 'current' => __( 'Current', 'siteorigin-panels' ),
330
+ 'revert' => __( 'Original', 'siteorigin-panels' ),
331
+ 'restore' => __( 'Version restored', 'siteorigin-panels' ),
332
+ 'back_to_editor' => __( 'Converted to editor', 'siteorigin-panels' ),
333
+
334
+ // Widgets
335
+ // TRANSLATORS: Message displayed in the history when a widget is deleted
336
+ 'widget_deleted' => __( 'Widget deleted', 'siteorigin-panels' ),
337
+ // TRANSLATORS: Message displayed in the history when a widget is added
338
+ 'widget_added' => __( 'Widget added', 'siteorigin-panels' ),
339
+ // TRANSLATORS: Message displayed in the history when a widget is edited
340
+ 'widget_edited' => __( 'Widget edited', 'siteorigin-panels' ),
341
+ // TRANSLATORS: Message displayed in the history when a widget is duplicated
342
+ 'widget_duplicated' => __( 'Widget duplicated', 'siteorigin-panels' ),
343
+ // TRANSLATORS: Message displayed in the history when a widget position is changed
344
+ 'widget_moved' => __( 'Widget moved', 'siteorigin-panels' ),
345
+
346
+ // Rows
347
+ // TRANSLATORS: Message displayed in the history when a row is deleted
348
+ 'row_deleted' => __( 'Row deleted', 'siteorigin-panels' ),
349
+ // TRANSLATORS: Message displayed in the history when a row is added
350
+ 'row_added' => __( 'Row added', 'siteorigin-panels' ),
351
+ // TRANSLATORS: Message displayed in the history when a row is edited
352
+ 'row_edited' => __( 'Row edited', 'siteorigin-panels' ),
353
+ // TRANSLATORS: Message displayed in the history when a row position is changed
354
+ 'row_moved' => __( 'Row moved', 'siteorigin-panels' ),
355
+ // TRANSLATORS: Message displayed in the history when a row is duplicated
356
+ 'row_duplicated' => __( 'Row duplicated', 'siteorigin-panels' ),
357
+ // TRANSLATORS: Message displayed in the history when a row is pasted
358
+ 'row_pasted' => __( 'Row pasted', 'siteorigin-panels' ),
359
+
360
+ // Cells
361
+ 'cell_resized' => __( 'Cell resized', 'siteorigin-panels' ),
362
+
363
+ // Prebuilt
364
+ 'prebuilt_loaded' => __( 'Prebuilt layout loaded', 'siteorigin-panels' ),
365
+ ),
366
+
367
+ // general localization
368
+ 'prebuilt_loading' => __( 'Loading prebuilt layout', 'siteorigin-panels' ),
369
+ 'confirm_use_builder' => __( "Would you like to copy this editor's existing content to Page Builder?", 'siteorigin-panels' ),
370
+ 'confirm_stop_builder' => __( "Would you like to clear your Page Builder content and revert to using the standard visual editor?", 'siteorigin-panels' ),
371
+ // TRANSLATORS: This is the title for a widget called "Layout Builder"
372
+ 'layout_widget' => __( 'Layout Builder Widget', 'siteorigin-panels' ),
373
+ // TRANSLATORS: A standard confirmation message
374
+ 'dropdown_confirm' => __( 'Are you sure?', 'siteorigin-panels' ),
375
+ // TRANSLATORS: When a layout file is ready to be inserted. %s is the filename.
376
+ 'ready_to_insert' => __( '%s is ready to insert.', 'siteorigin-panels' ),
377
+
378
+ // Everything for the contextual menu
379
+ 'contextual' => array(
380
+ 'add_widget_below' => __( 'Add Widget Below', 'siteorigin-panels' ),
381
+ 'add_widget_cell' => __( 'Add Widget to Cell', 'siteorigin-panels' ),
382
+ 'search_widgets' => __( 'Search Widgets', 'siteorigin-panels' ),
383
+
384
+ 'add_row' => __( 'Add Row', 'siteorigin-panels' ),
385
+ 'column' => __( 'Column', 'siteorigin-panels' ),
386
+
387
+ 'cell_actions' => __( 'Cell Actions', 'siteorigin-panels' ),
388
+ 'cell_paste_widget' => __( 'Paste Widget', 'siteorigin-panels' ),
389
+
390
+ 'widget_actions' => __( 'Widget Actions', 'siteorigin-panels' ),
391
+ 'widget_edit' => __( 'Edit Widget', 'siteorigin-panels' ),
392
+ 'widget_duplicate' => __( 'Duplicate Widget', 'siteorigin-panels' ),
393
+ 'widget_delete' => __( 'Delete Widget', 'siteorigin-panels' ),
394
+ 'widget_copy' => __( 'Copy Widget', 'siteorigin-panels' ),
395
+ 'widget_paste' => __( 'Paste Widget Below', 'siteorigin-panels' ),
396
+
397
+ 'row_actions' => __( 'Row Actions', 'siteorigin-panels' ),
398
+ 'row_edit' => __( 'Edit Row', 'siteorigin-panels' ),
399
+ 'row_duplicate' => __( 'Duplicate Row', 'siteorigin-panels' ),
400
+ 'row_delete' => __( 'Delete Row', 'siteorigin-panels' ),
401
+ 'row_copy' => __( 'Copy Row', 'siteorigin-panels' ),
402
+ 'row_paste' => __( 'Paste Row', 'siteorigin-panels' ),
403
+ ),
404
+ 'draft' => __( 'Draft', 'siteorigin-panels' ),
405
+ 'untitled' => __( 'Untitled', 'siteorigin-panels' ),
406
+ 'row' => array(
407
+ 'add' => __( 'New Row', 'siteorigin-panels' ),
408
+ 'edit' => __( 'Row', 'siteorigin-panels' ),
409
+ ),
410
+ 'welcomeMessage' => array(
411
+ 'addingDisabled' => __( 'Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements.', 'siteorigin-panels' ),
412
+ 'oneEnabled' => __( 'Add a {{%= items[0] %}} to get started.', 'siteorigin-panels' ),
413
+ 'twoEnabled' => __( 'Add a {{%= items[0] %}} or {{%= items[1] %}} to get started.', 'siteorigin-panels' ),
414
+ 'threeEnabled' => __( 'Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started.', 'siteorigin-panels' ),
415
+ 'addWidgetButton' => "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
416
+ 'addRowButton' => "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
417
+ 'addPrebuiltButton' => "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
418
+ 'docsMessage' => sprintf(
419
+ __( 'Read our %s if you need help.', 'siteorigin-panels' ),
420
+ "<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
421
+ ),
422
+ ),
423
+ ),
424
+ 'plupload' => array(
425
+ 'max_file_size' => wp_max_upload_size() . 'b',
426
+ 'url' => wp_nonce_url( admin_url( 'admin-ajax.php' ), 'panels_action', '_panelsnonce' ),
427
+ 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
428
+ 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
429
+ 'filter_title' => __( 'Page Builder layouts', 'siteorigin-panels' ),
430
+ 'error_message' => __( 'Error uploading or importing file.', 'siteorigin-panels' ),
431
+ ),
432
+ 'wpColorPickerOptions' => apply_filters( 'siteorigin_panels_wpcolorpicker_options', array() ),
433
+ 'prebuiltDefaultScreenshot' => siteorigin_panels_url( 'css/images/prebuilt-default.png' ),
434
+ 'loadOnAttach' => siteorigin_panels_setting( 'load-on-attach' ),
435
+ 'siteoriginWidgetRegex' => str_replace( '*+', '*', get_shortcode_regex( array( 'siteorigin_widget' ) ) ),
436
+ ) );
437
+
438
+ $js_widgets = array();
439
+ if ( $screen->base != 'widgets' ) {
440
+ // Render all the widget forms. A lot of widgets use this as a chance to enqueue their scripts
441
+ $original_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; // Make sure widgets don't change the global post.
442
+ global $wp_widget_factory;
443
+ foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
444
+ ob_start();
445
+ $return = $widget_obj->form( array() );
446
+ // These are the new widgets in WP 4.8 which are largely JS based. They only enqueue their own
447
+ // scripts on the 'widgets' screen.
448
+ if ( method_exists( $widget_obj, 'enqueue_admin_scripts' ) ) {
449
+ $widget_obj->enqueue_admin_scripts();
450
+ }
451
+ do_action_ref_array( 'in_widget_form', array( &$widget_obj, &$return, array() ) );
452
+ ob_end_clean();
453
+
454
+ // Need to render templates for new WP 4.8 widgets when not on the 'widgets' screen or in the customizer.
455
+ if ( $this->is_js_widget( $widget_obj ) ) {
456
+ $js_widgets[] = $widget_obj;
457
+ }
458
+ }
459
+ $GLOBALS['post'] = $original_post;
460
+ }
461
+
462
+ // This gives panels a chance to enqueue scripts too, without having to check the screen ID.
463
+ if ( $screen->base != 'widgets' && $screen->base != 'customize' ) {
464
+ foreach ( $js_widgets as $js_widget ) {
465
+ $js_widget->render_control_template_scripts();
466
+ }
467
+ do_action( 'siteorigin_panel_enqueue_admin_scripts' );
468
+ do_action( 'sidebar_admin_setup' );
469
+ }
470
+ }
471
+ }
472
+
473
+ /**
474
+ * Enqueue the admin panel styles
475
+ *
476
+ * @param string $prefix
477
+ * @param bool $force Should we force the enqueue
478
+ *
479
+ * @action admin_print_styles-post-new.php
480
+ * @action admin_print_styles-post.php
481
+ */
482
+ function enqueue_admin_styles( $prefix = '', $force = false ) {
483
+ if ( $force || self::is_admin() ) {
484
+ wp_enqueue_style(
485
+ 'so-panels-admin',
486
+ siteorigin_panels_url( 'css/admin' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
487
+ array( 'wp-color-picker' ),
488
+ SITEORIGIN_PANELS_VERSION
489
+ );
490
+ do_action( 'siteorigin_panel_enqueue_admin_styles' );
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Add a help tab to pages that include a Page Builder interface.
496
+ *
497
+ * @param $prefix
498
+ */
499
+ function add_help_tab( $prefix ) {
500
+ $screen = get_current_screen();
501
+ if (
502
+ ( $screen->base == 'post' && ( in_array( $screen->id, siteorigin_panels_setting( 'post-types' ) ) || $screen->id == '' ) )
503
+ || ( $screen->id == 'appearance_page_so_panels_home_page' )
504
+ ) {
505
+ $screen->add_help_tab( array(
506
+ 'id' => 'panels-help-tab', //unique id for the tab
507
+ 'title' => __( 'Page Builder', 'siteorigin-panels' ), //unique visible title for the tab
508
+ 'callback' => array( $this, 'help_tab_content' )
509
+ ) );
510
+ }
511
+ }
512
+
513
+ /**
514
+ * Display the content for the help tab.
515
+ */
516
+ function help_tab_content() {
517
+ include plugin_dir_path( __FILE__ ) . '../tpl/help.php';
518
+ }
519
+
520
+ /**
521
+ * Get the Page Builder data for the current admin page.
522
+ *
523
+ * @return array
524
+ */
525
+ function get_current_admin_panels_data() {
526
+ $screen = get_current_screen();
527
+
528
+ // Localize the panels with the panels data
529
+ if ( $screen->base == 'appearance_page_so_panels_home_page' ) {
530
+ $home_page_id = get_option( 'page_on_front' );
531
+ if ( empty( $home_page_id ) ) {
532
+ $home_page_id = get_option( 'siteorigin_panels_home_page_id' );
533
+ }
534
+
535
+ $panels_data = ! empty( $home_page_id ) ? get_post_meta( $home_page_id, 'panels_data', true ) : null;
536
+
537
+ if ( is_null( $panels_data ) ) {
538
+ // Load the default layout
539
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
540
+
541
+ $home_name = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
542
+ $panels_data = ! empty( $layouts[ $home_name ] ) ? $layouts[ $home_name ] : current( $layouts );
543
+ } elseif ( empty( $panels_data ) ) {
544
+ // The current page_on_front isn't using page builder
545
+ return false;
546
+ }
547
+
548
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, 'home' );
549
+ } else {
550
+ global $post;
551
+ $panels_data = get_post_meta( $post->ID, 'panels_data', true );
552
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post->ID );
553
+ }
554
+
555
+ if ( empty( $panels_data ) ) {
556
+ $panels_data = array();
557
+ }
558
+
559
+ return $panels_data;
560
+ }
561
+
562
+ /**
563
+ * Save home page
564
+ */
565
+ function save_home_page() {
566
+ if ( ! isset( $_POST['_sopanels_home_nonce'] ) || ! wp_verify_nonce( $_POST['_sopanels_home_nonce'], 'save' ) ) {
567
+ return;
568
+ }
569
+ if ( ! current_user_can( 'edit_theme_options' ) ) {
570
+ return;
571
+ }
572
+ if ( ! isset( $_POST['panels_data'] ) ) {
573
+ return;
574
+ }
575
+
576
+ // Check that the home page ID is set and the home page exists
577
+ $page_id = get_option( 'page_on_front' );
578
+ if ( empty( $page_id ) ) {
579
+ $page_id = get_option( 'siteorigin_panels_home_page_id' );
580
+ }
581
+
582
+ $post_content = wp_unslash( $_POST['post_content'] );
583
+
584
+ if ( ! $page_id || get_post_meta( $page_id, 'panels_data', true ) == '' ) {
585
+ // Lets create a new page
586
+ $page_id = wp_insert_post( array(
587
+ // TRANSLATORS: This is the default name given to a user's home page
588
+ 'post_title' => __( 'Home Page', 'siteorigin-panels' ),
589
+ 'post_status' => ! empty( $_POST['siteorigin_panels_home_enabled'] ) ? 'publish' : 'draft',
590
+ 'post_type' => 'page',
591
+ 'post_content' => $post_content,
592
+ 'comment_status' => 'closed',
593
+ ) );
594
+ update_option( 'page_on_front', $page_id );
595
+ update_option( 'siteorigin_panels_home_page_id', $page_id );
596
+
597
+ // Action triggered when creating a new home page through the custom home page interface
598
+ do_action( 'siteorigin_panels_create_home_page', $page_id );
599
+ } else {
600
+ // `wp_insert_post` does it's own sanitization, but it seems `wp_update_post` doesn't.
601
+ $post_content = sanitize_post_field( 'post_content', $post_content, $page_id, 'db' );
602
+
603
+ // Update the post with changed content to save revision if necessary.
604
+ wp_update_post( array( 'ID' => $page_id, 'post_content' => $post_content ) );
605
+ }
606
+
607
+ $page = get_post( $page_id );
608
+
609
+ // Save the updated page data
610
+ $old_panels_data = get_post_meta( $page_id, 'panels_data', true );
611
+ $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
612
+ $panels_data['widgets'] = $this->process_raw_widgets(
613
+ $panels_data['widgets'],
614
+ ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
615
+ false
616
+ );
617
+ $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
618
+ $panels_data = apply_filters( 'siteorigin_panels_data_pre_save', $panels_data, $page, $page_id );
619
+
620
+ update_post_meta( $page_id, 'panels_data', map_deep( $panels_data, array( 'SiteOrigin_Panels_Admin', 'double_slash_string' ) ) );
621
+
622
+ $template = get_post_meta( $page_id, '_wp_page_template', true );
623
+ $home_template = siteorigin_panels_setting( 'home-template' );
624
+ if ( ( $template == '' || $template == 'default' ) && ! empty( $home_template ) ) {
625
+ // Set the home page template
626
+ update_post_meta( $page_id, '_wp_page_template', $home_template );
627
+ }
628
+
629
+ if ( ! empty( $_POST['siteorigin_panels_home_enabled'] ) ) {
630
+ update_option( 'show_on_front', 'page' );
631
+ update_option( 'page_on_front', $page_id );
632
+ update_option( 'siteorigin_panels_home_page_id', $page_id );
633
+ wp_publish_post( $page_id );
634
+ } else {
635
+ // We're disabling this home page
636
+ update_option( 'show_on_front', 'posts' );
637
+
638
+ // Change the post status to draft
639
+ $post = get_post( $page_id );
640
+ if ( $post->post_status != 'draft' ) {
641
+ global $wpdb;
642
+
643
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $post->ID ) );
644
+ clean_post_cache( $post->ID );
645
+
646
+ $old_status = $post->post_status;
647
+ $post->post_status = 'draft';
648
+ wp_transition_post_status( 'draft', $old_status, $post );
649
+
650
+ do_action( 'edit_post', $post->ID, $post );
651
+ do_action( "save_post_{$post->post_type}", $post->ID, $post, true );
652
+ do_action( 'save_post', $post->ID, $post, true );
653
+ do_action( 'wp_insert_post', $post->ID, $post, true );
654
+ }
655
+ }
656
+ }
657
+
658
+ /**
659
+ * After the theme is switched, change the template on the home page if the theme supports home page functionality.
660
+ */
661
+ function update_home_on_theme_change() {
662
+ $page_id = get_option( 'page_on_front' );
663
+ if ( empty( $page_id ) ) {
664
+ $page_id = get_option( 'siteorigin_panels_home_page_id' );
665
+ }
666
+
667
+ if ( siteorigin_panels_setting( 'home-page' ) && siteorigin_panels_setting( 'home-template' ) && $page_id && get_post_meta( $page_id, 'panels_data', true ) !== '' ) {
668
+ // Lets update the home page to use the home template that this theme supports
669
+ update_post_meta( $page_id, '_wp_page_template', siteorigin_panels_setting( 'home-template' ) );
670
+ }
671
+ }
672
+
673
+ /**
674
+ * @return array|mixed|void
675
+ */
676
+ function get_widgets() {
677
+ global $wp_widget_factory;
678
+ $widgets = array();
679
+ foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
680
+ $widgets[ $class ] = array(
681
+ 'class' => $class,
682
+ 'title' => ! empty( $widget_obj->name ) ? $widget_obj->name : __( 'Untitled Widget', 'siteorigin-panels' ),
683
+ 'description' => ! empty( $widget_obj->widget_options['description'] ) ? $widget_obj->widget_options['description'] : '',
684
+ 'installed' => true,
685
+ 'groups' => array(),
686
+ );
687
+
688
+ // Get Page Builder specific widget options
689
+ if ( isset( $widget_obj->widget_options['panels_title'] ) ) {
690
+ $widgets[ $class ]['panels_title'] = $widget_obj->widget_options['panels_title'];
691
+ }
692
+ if ( isset( $widget_obj->widget_options['panels_groups'] ) ) {
693
+ $widgets[ $class ]['groups'] = $widget_obj->widget_options['panels_groups'];
694
+ }
695
+ if ( isset( $widget_obj->widget_options['panels_icon'] ) ) {
696
+ $widgets[ $class ]['icon'] = $widget_obj->widget_options['panels_icon'];
697
+ }
698
+
699
+ }
700
+
701
+ // Other plugins can manipulate the list of widgets. Possibly to add recommended widgets
702
+ $widgets = apply_filters( 'siteorigin_panels_widgets', $widgets );
703
+
704
+ // Sort the widgets alphabetically
705
+ uasort( $widgets, array( $this, 'widgets_sorter' ) );
706
+
707
+ return $widgets;
708
+ }
709
+
710
+ /**
711
+ * Sorts widgets for get_widgets function by title
712
+ *
713
+ * @param $a
714
+ * @param $b
715
+ *
716
+ * @return int
717
+ */
718
+ function widgets_sorter( $a, $b ) {
719
+ if ( empty( $a['title'] ) ) {
720
+ return - 1;
721
+ }
722
+ if ( empty( $b['title'] ) ) {
723
+ return 1;
724
+ }
725
+
726
+ return $a['title'] > $b['title'] ? 1 : - 1;
727
+ }
728
+
729
+ /**
730
+ * Process raw widgets that have come from the Page Builder front end.
731
+ *
732
+ * @param array $widgets An array of widgets from panels_data.
733
+ * @param array $old_widgets
734
+ * @param bool $escape_classes Should the class names be escaped.
735
+ * @param bool $force
736
+ *
737
+ * @return array
738
+ */
739
+ function process_raw_widgets( $widgets, $old_widgets = array(), $escape_classes = false, $force = false ) {
740
+ if ( empty( $widgets ) || ! is_array( $widgets ) ) {
741
+ return array();
742
+ }
743
+
744
+ global $wp_widget_factory;
745
+
746
+ $old_widgets_by_id = array();
747
+ if( ! empty( $old_widgets ) ) {
748
+ foreach( $old_widgets as $widget ) {
749
+ if( ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) ) {
750
+ $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] = $widget;
751
+ unset( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ][ 'panels_info' ] );
752
+ }
753
+ }
754
+ }
755
+
756
+ foreach( $widgets as $i => & $widget ) {
757
+ if ( ! is_array( $widget ) ) {
758
+ continue;
759
+ }
760
+
761
+ if ( is_array( $widget ) ) {
762
+ $info = (array) ( is_array( $widget['panels_info'] ) ? $widget['panels_info'] : $widget['info'] );
763
+ } else {
764
+ $info = array();
765
+ }
766
+ unset( $widget['info'] );
767
+
768
+ $info[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $info[ 'class' ] );
769
+
770
+ if ( ! empty( $info['raw'] ) || $force ) {
771
+ if ( isset( $wp_widget_factory->widgets[ $info['class'] ] ) && method_exists( $info['class'], 'update' ) ) {
772
+
773
+ if(
774
+ ! empty( $old_widgets_by_id ) &&
775
+ ! empty( $widget[ 'panels_info' ][ 'widget_id' ] ) &&
776
+ ! empty( $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ] )
777
+ ){
778
+ $old_widget = $old_widgets_by_id[ $widget[ 'panels_info' ][ 'widget_id' ] ];
779
+ }
780
+ else {
781
+ $old_widget = $widget;
782
+ }
783
+
784
+ /** @var WP_Widget $the_widget */
785
+ $the_widget = $wp_widget_factory->widgets[ $info['class'] ];
786
+ $instance = $the_widget->update( $widget, $old_widget );
787
+ $instance = apply_filters( 'widget_update_callback', $instance, $widget, $old_widget, $the_widget );
788
+
789
+ $widget = $instance;
790
+ unset( $info['raw'] );
791
+ }
792
+ }
793
+
794
+ if( $escape_classes ) {
795
+ // Escaping for namespaced widgets
796
+ $info[ 'class' ] = preg_replace( '/\\\\+/', '\\\\\\\\', $info['class'] );
797
+ }
798
+ $widget['panels_info'] = $info;
799
+ }
800
+
801
+ return $widgets;
802
+ }
803
+
804
+ /**
805
+ * Add all the footer JS templates.
806
+ */
807
+ function js_templates() {
808
+ include plugin_dir_path( __FILE__ ) . '../tpl/js-templates.php';
809
+ }
810
+
811
+ /**
812
+ * Render a widget form with all the Page Builder specific fields
813
+ *
814
+ * @param string $widget The class of the widget
815
+ * @param array $instance Widget values
816
+ * @param bool $raw
817
+ * @param string $widget_number
818
+ *
819
+ * @return mixed|string The form
820
+ */
821
+ function render_form( $widget, $instance = array(), $raw = false, $widget_number = '{$id}' ) {
822
+ global $wp_widget_factory;
823
+
824
+ // This is a chance for plugins to replace missing widgets
825
+ $the_widget = ! empty( $wp_widget_factory->widgets[ $widget ] ) ? $wp_widget_factory->widgets[ $widget ] : false;
826
+ $the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget );
827
+
828
+ if ( empty( $the_widget ) || ! is_a( $the_widget, 'WP_Widget' ) ) {
829
+ $widgets = $this->get_widgets();
830
+
831
+ if ( ! empty( $widgets[ $widget ] ) && ! empty( $widgets[ $widget ]['plugin'] ) ) {
832
+ // We know about this widget, show a form about installing it.
833
+ $install_url = siteorigin_panels_plugin_activation_install_url( $widgets[ $widget ]['plugin']['slug'], $widgets[ $widget ]['plugin']['name'] );
834
+ $form =
835
+ '<div class="panels-missing-widget-form">' .
836
+ '<p>' .
837
+ preg_replace(
838
+ array(
839
+ '/1\{ *(.*?) *\}/',
840
+ '/2\{ *(.*?) *\}/',
841
+ ),
842
+ array(
843
+ '<a href="' . $install_url . '" target="_blank" rel="noopener noreferrer">$1</a>',
844
+ '<strong>$1</strong>'
845
+ ),
846
+ sprintf(
847
+ __( 'You need to install 1{%1$s} to use the widget 2{%2$s}.', 'siteorigin-panels' ),
848
+ $widgets[ $widget ]['plugin']['name'],
849
+ $widget
850
+ )
851
+ ) .
852
+ '</p>' .
853
+ '<p>' . __( "Save and reload this page to start using the widget after you've installed it.", 'siteorigin-panels' ) . '</p>' .
854
+ '</div>';
855
+ } else {
856
+ // This widget is missing, so show a missing widgets form.
857
+ $form =
858
+ '<div class="panels-missing-widget-form"><p>' .
859
+ preg_replace(
860
+ array(
861
+ '/1\{ *(.*?) *\}/',
862
+ '/2\{ *(.*?) *\}/',
863
+ ),
864
+ array(
865
+ '<strong>$1</strong>',
866
+ '<a href="https://siteorigin.com/thread/" target="_blank" rel="noopener noreferrer">$1</a>'
867
+ ),
868
+ sprintf(
869
+ __( 'The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help.', 'siteorigin-panels' ),
870
+ esc_html( $widget )
871
+ )
872
+ ) .
873
+ '</p></div>';
874
+ }
875
+
876
+ // Allow other themes and plugins to change the missing widget form
877
+ return apply_filters( 'siteorigin_panels_missing_widget_form', $form, $widget, $instance );
878
+ }
879
+
880
+ if ( $raw ) {
881
+ $instance = $the_widget->update( $instance, $instance );
882
+ }
883
+
884
+ $the_widget->id = 'temp';
885
+ $the_widget->number = $widget_number;
886
+
887
+ ob_start();
888
+ if ( $this->is_js_widget( $the_widget ) ) {
889
+ ?><div class="widget-content"><?php
890
+ }
891
+ $return = $the_widget->form( $instance );
892
+ do_action_ref_array( 'in_widget_form', array( &$the_widget, &$return, $instance ) );
893
+ if ( $this->is_js_widget( $the_widget ) ) {
894
+ ?>
895
+ </div>
896
+ <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $the_widget->id_base ); ?>" />
897
+ <?php
898
+ }
899
+ $form = ob_get_clean();
900
+
901
+ // Convert the widget field naming into ones that Page Builder uses
902
+ $exp = preg_quote( $the_widget->get_field_name( '____' ) );
903
+ $exp = str_replace( '____', '(.*?)', $exp );
904
+ $form = preg_replace( '/' . $exp . '/', 'widgets[' . preg_replace( '/\$(\d)/', '\\\$$1', $widget_number ) . '][$1]', $form );
905
+
906
+ $form = apply_filters( 'siteorigin_panels_widget_form', $form, $widget, $instance );
907
+
908
+ // Add all the information fields
909
+ return $form;
910
+ }
911
+
912
+ function is_js_widget( $widget ) {
913
+ $js_widgets = array(
914
+ 'WP_Widget_Custom_HTML',
915
+ 'WP_Widget_Media_Audio',
916
+ 'WP_Widget_Media_Gallery',
917
+ 'WP_Widget_Media_Image',
918
+ 'WP_Widget_Media_Video',
919
+ 'WP_Widget_Text',
920
+ );
921
+
922
+ $is_js_widget = in_array( get_class( $widget ), $js_widgets ) &&
923
+ // Need to check this for `WP_Widget_Text` which was not a JS widget before 4.8
924
+ method_exists( $widget, 'render_control_template_scripts' );
925
+
926
+ return $is_js_widget;
927
+ }
928
+
929
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
930
+ // ADMIN AJAX ACTIONS
931
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
932
+
933
+ /**
934
+ * Get builder content based on the submitted panels_data.
935
+ */
936
+ function action_builder_content() {
937
+ header( 'content-type: text/html' );
938
+
939
+ if ( ! current_user_can( 'edit_post', $_POST['post_id'] ) ) {
940
+ wp_die();
941
+ }
942
+
943
+ if ( empty( $_POST['post_id'] ) || empty( $_POST['panels_data'] ) ) {
944
+ echo '';
945
+ wp_die();
946
+ }
947
+
948
+ // echo the content
949
+ $old_panels_data = get_post_meta( $_POST['post_id'], 'panels_data', true );
950
+ $panels_data = json_decode( wp_unslash( $_POST['panels_data'] ), true );
951
+ $panels_data['widgets'] = $this->process_raw_widgets(
952
+ $panels_data['widgets'],
953
+ ! empty( $old_panels_data['widgets'] ) ? $old_panels_data['widgets'] : false,
954
+ false
955
+ );
956
+ $panels_data = SiteOrigin_Panels_Styles_Admin::single()->sanitize_all( $panels_data );
957
+
958
+ // Create a version of the builder data for post content
959
+ SiteOrigin_Panels_Post_Content_Filters::add_filters();
960
+ $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] = true;
961
+ echo SiteOrigin_Panels::renderer()->render( intval( $_POST['post_id'] ), false, $panels_data );
962
+ SiteOrigin_Panels_Post_Content_Filters::remove_filters();
963
+ unset( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] );
964
+
965
+ wp_die();
966
+ }
967
+
968
+ /**
969
+ * Display a widget form with the provided data
970
+ */
971
+ function action_widget_form() {
972
+ if ( empty( $_REQUEST['widget'] ) ) {
973
+ wp_die();
974
+ }
975
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'panels_action' ) ) {
976
+ wp_die();
977
+ }
978
+
979
+ $request = array_map( 'stripslashes_deep', $_REQUEST );
980
+
981
+ $widget_class = $request['widget'];
982
+ $widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
983
+ $instance = ! empty( $request['instance'] ) ? json_decode( $request['instance'], true ) : array();
984
+
985
+ $form = $this->render_form( $widget_class, $instance, $_REQUEST['raw'] == 'true' );
986
+ $form = apply_filters( 'siteorigin_panels_ajax_widget_form', $form, $widget_class, $instance );
987
+
988
+ echo $form;
989
+ wp_die();
990
+ }
991
+
992
+ /**
993
+ * Preview in the live editor when there is no public view of the item
994
+ */
995
+ function action_live_editor_preview() {
996
+ if ( empty( $_REQUEST['_panelsnonce'] ) || ! wp_verify_nonce( $_REQUEST['_panelsnonce'], 'live-editor-preview' ) ) {
997
+ wp_die();
998
+ }
999
+
1000
+ include plugin_dir_path( __FILE__ ) . '../tpl/live-editor-preview.php';
1001
+
1002
+ exit();
1003
+ }
1004
+
1005
+ /**
1006
+ * Add a column that indicates if a column is powered by Page Builder
1007
+ *
1008
+ * @param $columns
1009
+ *
1010
+ * @return array
1011
+ */
1012
+ function add_custom_column( $columns ){
1013
+ $index = array_search( 'comments', array_keys( $columns ) );
1014
+
1015
+ if( empty( $index ) ) {
1016
+ $columns = array_merge(
1017
+ $columns,
1018
+ array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) )
1019
+ );
1020
+ }
1021
+ else {
1022
+ $columns = array_slice( $columns, 0, $index, true ) +
1023
+ array( 'panels' => __( 'Page Builder', 'siteorigin-panels' ) ) +
1024
+ array_slice( $columns, $index, count( $columns ) - 1, true );
1025
+ }
1026
+
1027
+ return $columns;
1028
+ }
1029
+
1030
+ function display_custom_column( $column, $post_id ){
1031
+ if( $column != 'panels' ) return;
1032
+
1033
+ $panels_data = get_post_meta( $post_id, 'panels_data', true );
1034
+ if( ! empty( $panels_data['widgets'] ) ) {
1035
+ printf( __( '%s Widgets', 'siteorigin-panels' ), count( $panels_data['widgets'] ) );
1036
+ }
1037
+ else {
1038
+ echo '—';
1039
+ }
1040
+ }
1041
+
1042
+ public function footer_column_css(){
1043
+ if( siteorigin_panels_setting( 'admin-widget-count' ) ) {
1044
+ $screen = get_current_screen();
1045
+ $post_types = siteorigin_panels_setting( 'post-types' );
1046
+
1047
+ if(
1048
+ $screen->base == 'edit' &&
1049
+ is_array( $post_types ) &&
1050
+ in_array( $screen->post_type, $post_types )
1051
+ ){
1052
+ ?><style type="text/css">.column-panels{ width: 10% }</style><?php
1053
+ }
1054
+ }
1055
+ }
1056
+
1057
+ /**
1058
+ * Add double slashes to strings
1059
+ *
1060
+ * @param $value
1061
+ *
1062
+ * @return string
1063
+ */
1064
+ public static function double_slash_string( $value ){
1065
+ return is_string( $value ) ? addcslashes( $value, '\\' ) : $value;
1066
+ }
1067
+
1068
+ public function get_layout_directories(){
1069
+
1070
+ }
1071
+
1072
+ /**
1073
+ * Add all the courses to the learning dialog
1074
+ *
1075
+ * @param $lessons
1076
+ *
1077
+ * @return mixed
1078
+ */
1079
+ public function filter_learn_lessons( $lessons ) {
1080
+ $lessons['page-builder-tips'] = array(
1081
+ 'title' => __( '12 Page Builder Tips', 'siteorigin-panels' ),
1082
+ 'video' => '212380146',
1083
+ 'poster' => siteorigin_panels_url( 'posters/page-builder-tips.svg' ),
1084
+ 'description' => __( "Sign up to our newsletter and we'll send you this free Page Builder video course.", 'siteorigin-panels' ) . ' ' .
1085
+ __( "12 tips that'll help you get the most out of Page Builder.", 'siteorigin-panels' ) . ' ' .
1086
+ __( "Watch the video to find out more, then sign up below to get started.", 'siteorigin-panels' ),
1087
+ 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1088
+ );
1089
+
1090
+ $lessons['page-builder-animations'] = array(
1091
+ 'title' => __( 'Free Page Builder Addons', 'siteorigin-panels' ),
1092
+ 'video' => '212380210',
1093
+ 'poster' => siteorigin_panels_url( 'posters/addons.svg' ),
1094
+ 'description' => __( "The free animations addon allows you to add beautiful animations to Page Builder elements.", 'siteorigin-panels' ) . ' ' .
1095
+ __( "Sign up to our newsletter and we'll send you the addon as a free gift.", 'siteorigin-panels' ) . ' ' .
1096
+ __( "Plus, we'll send you even more powerful addons, for as long as you're subscribed.", 'siteorigin-panels' ),
1097
+ 'form_description' => __( "We'll email you a confirmation. You can unsubscribe at any time.", 'siteorigin-panels' ),
1098
+ );
1099
+
1100
+ return $lessons;
1101
+ }
1102
+
1103
+ /**
1104
+ * Filter the translation strings for SiteOrigin learning dialogs
1105
+ *
1106
+ * @param $strings
1107
+ *
1108
+ * @return array
1109
+ */
1110
+ public function filter_learn_strings( $strings ){
1111
+ $strings = array(
1112
+ 'watch_video' => __( 'Watch Intro Video', 'siteorigin-panels' ),
1113
+ 'loaded_from_vimeo' => __( 'Loaded from Vimeo Servers', 'siteorigin-panels' ),
1114
+ 'valid_email' => __( 'Please enter a valid email address.', 'siteorigin-panels' ),
1115
+
1116
+ 'your_name' => __( 'Your Name', 'siteorigin-panels' ),
1117
+ 'your_email' => __( 'Your Email', 'siteorigin-panels' ),
1118
+ 'sign_up' => __( 'Sign Up', 'siteorigin-panels' ),
1119
+ 'close' => __( 'Close', 'siteorigin-panels' ),
1120
+ );
1121
+ return $strings;
1122
+ }
1123
+
1124
+ /**
1125
+ * Display links for various SiteOrigin addons
1126
+ */
1127
+ public static function display_footer_premium_link(){
1128
+ $links = array(
1129
+ array(
1130
+ 'text' => __('Get a lightbox addon for SiteOrigin widgets', 'siteorigin-panels'),
1131
+ 'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
1132
+ ),
1133
+ array(
1134
+ 'text' => __('Get the row, cell and widget animations addon', 'siteorigin-panels'),
1135
+ 'url' => SiteOrigin_Panels::premium_url('plugin/lightbox')
1136
+ ),
1137
+ array(
1138
+ 'text' => __('Get premium email support for SiteOrigin Page Builder', 'siteorigin-panels'),
1139
+ 'url' => SiteOrigin_Panels::premium_url()
1140
+ ),
1141
+ );
1142
+ $link = $links[array_rand($links)];
1143
+
1144
+ ?>
1145
+ <a href="<?php echo esc_url( $link['url'] ) ?>" target="_blank" rel='noopener noreferrer'>
1146
+ <?php echo esc_html( $link['text'] ) ?>.
1147
+ </a>
1148
+ <?php
1149
+ }
1150
+
1151
+ /**
1152
+ * Disable the Gutenberg editor for existing PB posts.
1153
+ *
1154
+ * @param $can_edit
1155
+ * @param $post_type
1156
+ *
1157
+ * @return bool
1158
+ */
1159
+ public function disable_gutenberg_for_panels_posts( $can_edit, $post_type ) {
1160
+ $screen = get_current_screen();
1161
+ $post_types = siteorigin_panels_setting( 'post-types' );
1162
+ $panels_data = $screen->base == 'post' ? $this->get_current_admin_panels_data() : array();
1163
+
1164
+ $is_panels_page = in_array( $post_type, $post_types ) && ! empty( $panels_data );
1165
+
1166
+ return ! $is_panels_page && $can_edit;
1167
+ }
1168
+
1169
+ /**
1170
+ * Disable PB when we're in the Gutenberg editor.
1171
+ *
1172
+ * @param $wp_meta_boxes
1173
+ *
1174
+ * @return mixed
1175
+ */
1176
+ public function disable_panels_for_gutenberg_posts( $wp_meta_boxes ) {
1177
+ foreach ( $wp_meta_boxes as &$locations ) {
1178
+ foreach ( $locations as &$priorities ) {
1179
+ foreach ( $priorities as &$boxes ) {
1180
+ unset( $boxes['so-panels-panels'] );
1181
+ unset( $boxes['siteorigin_page_settings'] );
1182
+
1183
+ }
1184
+ }
1185
+ }
1186
+ return $wp_meta_boxes;
1187
+ }
1188
+ }
inc/cache-renderer.php CHANGED
@@ -1,41 +1,37 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Cache_Renderer {
4
-
5
- function __construct() {
6
- // Clear cache when the Page Builder version changes
7
- add_action( 'siteorigin_panels_version_changed', array( $this, 'clear_cache' ), 10, 0 );
8
-
9
- // When we activate/deactivate a plugin or switch themes that might change rendering
10
- add_action( 'activated_plugin', array( $this, 'clear_cache' ), 10, 0 );
11
- add_action( 'deactivated_plugin', array( $this, 'clear_cache' ), 10, 0 );
12
- add_action( 'switch_theme', array( $this, 'clear_cache' ), 10, 0 );
13
-
14
- // When settings are saved, this is also a good way to force a cache refresh
15
- add_action( 'siteorigin_panels_save_settings', array( $this, 'clear_cache' ), 10, 0 );
16
-
17
- // When a single post is saved
18
- add_action( 'save_post', array( $this, 'clear_cache' ), 10, 2 );
19
- }
20
-
21
- /**
22
- * @return SiteOrigin_Panels_Cache_Renderer
23
- */
24
- static function single() {
25
- static $single;
26
- return empty( $single ) ? $single = new self() : $single;
27
- }
28
-
29
- /**
30
- * Clear post meta cache.
31
- *
32
- * Keep this around for a bit in attempt to delete any existing caches.
33
- *
34
- * @param bool|int $post_id The ID of the post to clear or false for all
35
- */
36
- public function clear_cache( $post_id = false ){
37
- global $wpdb;
38
-
39
- $wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = 'siteorigin_panels_cache'" );
40
- }
41
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Cache_Renderer {
4
+
5
+ function __construct() {
6
+ // Clear cache when the Page Builder version changes
7
+ add_action( 'siteorigin_panels_version_changed', array( $this, 'clear_cache' ), 10, 0 );
8
+
9
+ // When we activate/deactivate a plugin or switch themes that might change rendering
10
+ add_action( 'activated_plugin', array( $this, 'clear_cache' ), 10, 0 );
11
+ add_action( 'deactivated_plugin', array( $this, 'clear_cache' ), 10, 0 );
12
+ add_action( 'switch_theme', array( $this, 'clear_cache' ), 10, 0 );
13
+
14
+ // When settings are saved, this is also a good way to force a cache refresh
15
+ add_action( 'siteorigin_panels_save_settings', array( $this, 'clear_cache' ), 10, 0 );
16
+
17
+ // When a single post is saved
18
+ add_action( 'save_post', array( $this, 'clear_cache' ), 10, 2 );
19
+ }
20
+
21
+ /**
22
+ * @return SiteOrigin_Panels_Cache_Renderer
23
+ */
24
+ static function single() {
25
+ static $single;
26
+ return empty( $single ) ? $single = new self() : $single;
27
+ }
28
+
29
+ /**
30
+ * Clear post meta cache.
31
+ *
32
+ * Keep this around for a bit in attempt to delete any existing caches.
33
+ */
34
+ public function clear_cache(){
35
+ delete_post_meta_by_key( 'siteorigin_panels_cache' );
36
+ }
37
+ }
 
 
 
 
inc/live-editor.php CHANGED
@@ -1,95 +1,95 @@
1
- <?php
2
-
3
- /**
4
- * The live editor class. Only loaded when in live editor mode.
5
- *
6
- * Class SiteOrigin_Panels_Live_Editor
7
- */
8
- class SiteOrigin_Panels_Live_Editor {
9
-
10
- function __construct() {
11
- add_action( 'template_redirect', array( $this, 'xss_headers' ) );
12
- add_action( 'get_post_metadata', array( $this, 'post_metadata' ), 10, 3 );
13
- add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
14
-
15
- // Don't display the admin bar when in live editor mode
16
- add_filter( 'show_admin_bar', '__return_false' );
17
- }
18
-
19
- public static function single() {
20
- static $single;
21
- return empty( $single ) ? $single = new self() : $single;
22
- }
23
-
24
- public function xss_headers(){
25
- global $post;
26
- if(
27
- ! empty( $_POST['live_editor_panels_data'] ) &&
28
- ! empty( $post->ID ) &&
29
- current_user_can( 'edit_post', $post->ID )
30
- ) {
31
- // Disable XSS protection when in the Live Editor
32
- header( 'X-XSS-Protection: 0' );
33
- }
34
- }
35
-
36
- /**
37
- * Edit the page builder data when we're viewing the live editor version
38
- *
39
- * @param $value
40
- * @param $post_id
41
- * @param $meta_key
42
- *
43
- * @return array
44
- */
45
- function post_metadata( $value, $post_id, $meta_key ) {
46
- if (
47
- $meta_key == 'panels_data' &&
48
- current_user_can( 'edit_post', $post_id ) &&
49
- ! empty( $_POST['live_editor_panels_data'] ) &&
50
- $_POST['live_editor_post_ID'] == $post_id
51
- ) {
52
- $data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
53
-
54
- if (
55
- ! empty( $data['widgets'] ) && (
56
- ! class_exists( 'SiteOrigin_Widget_Field_Class_Loader' ) ||
57
- method_exists( 'SiteOrigin_Widget_Field_Class_Loader', 'extend' )
58
- )
59
- ) {
60
- $data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $data['widgets'], false, false );
61
- }
62
-
63
- $value = array( $data );
64
- }
65
-
66
- return $value;
67
- }
68
-
69
-
70
- /**
71
- * Load the frontend scripts for the live editor
72
- */
73
- function frontend_scripts() {
74
- wp_enqueue_script(
75
- 'live-editor-front',
76
- siteorigin_panels_url( 'js/live-editor/live-editor-front' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
77
- array( 'jquery' ),
78
- SITEORIGIN_PANELS_VERSION
79
- );
80
-
81
- wp_enqueue_script(
82
- 'live-editor-scrollto',
83
- siteorigin_panels_url( 'js/live-editor/jquery.scrollTo' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
84
- array( 'jquery' ),
85
- SITEORIGIN_PANELS_VERSION
86
- );
87
-
88
- wp_enqueue_style(
89
- 'live-editor-front',
90
- siteorigin_panels_url( 'css/live-editor-front.css' ),
91
- array(),
92
- SITEORIGIN_PANELS_VERSION
93
- );
94
- }
95
- }
1
+ <?php
2
+
3
+ /**
4
+ * The live editor class. Only loaded when in live editor mode.
5
+ *
6
+ * Class SiteOrigin_Panels_Live_Editor
7
+ */
8
+ class SiteOrigin_Panels_Live_Editor {
9
+
10
+ function __construct() {
11
+ add_action( 'template_redirect', array( $this, 'xss_headers' ) );
12
+ add_action( 'get_post_metadata', array( $this, 'post_metadata' ), 10, 3 );
13
+ add_action( 'wp_enqueue_scripts', array( $this, 'frontend_scripts' ) );
14
+
15
+ // Don't display the admin bar when in live editor mode
16
+ add_filter( 'show_admin_bar', '__return_false' );
17
+ }
18
+
19
+ public static function single() {
20
+ static $single;
21
+ return empty( $single ) ? $single = new self() : $single;
22
+ }
23
+
24
+ public function xss_headers(){
25
+ global $post;
26
+ if(
27
+ ! empty( $_POST['live_editor_panels_data'] ) &&
28
+ ! empty( $post->ID ) &&
29
+ current_user_can( 'edit_post', $post->ID )
30
+ ) {
31
+ // Disable XSS protection when in the Live Editor
32
+ header( 'X-XSS-Protection: 0' );
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Edit the page builder data when we're viewing the live editor version
38
+ *
39
+ * @param $value
40
+ * @param $post_id
41
+ * @param $meta_key
42
+ *
43
+ * @return array
44
+ */
45
+ function post_metadata( $value, $post_id, $meta_key ) {
46
+ if (
47
+ $meta_key == 'panels_data' &&
48
+ current_user_can( 'edit_post', $post_id ) &&
49
+ ! empty( $_POST['live_editor_panels_data'] ) &&
50
+ $_POST['live_editor_post_ID'] == $post_id
51
+ ) {
52
+ $data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
53
+
54
+ if (
55
+ ! empty( $data['widgets'] ) && (
56
+ ! class_exists( 'SiteOrigin_Widget_Field_Class_Loader' ) ||
57
+ method_exists( 'SiteOrigin_Widget_Field_Class_Loader', 'extend' )
58
+ )
59
+ ) {
60
+ $data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $data['widgets'], false, false );
61
+ }
62
+
63
+ $value = array( $data );
64
+ }
65
+
66
+ return $value;
67
+ }
68
+
69
+
70
+ /**
71
+ * Load the frontend scripts for the live editor
72
+ */
73
+ function frontend_scripts() {
74
+ wp_enqueue_script(
75
+ 'live-editor-front',
76
+ siteorigin_panels_url( 'js/live-editor/live-editor-front' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
77
+ array( 'jquery' ),
78
+ SITEORIGIN_PANELS_VERSION
79
+ );
80
+
81
+ wp_enqueue_script(
82
+ 'live-editor-scrollto',
83
+ siteorigin_panels_url( 'js/live-editor/jquery.scrollTo' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
84
+ array( 'jquery' ),
85
+ SITEORIGIN_PANELS_VERSION
86
+ );
87
+
88
+ wp_enqueue_style(
89
+ 'live-editor-front',
90
+ siteorigin_panels_url( 'css/live-editor-front' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ),
91
+ array(),
92
+ SITEORIGIN_PANELS_VERSION
93
+ );
94
+ }
95
+ }
inc/renderer.php CHANGED
@@ -1,794 +1,794 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Renderer {
4
-
5
- private $inline_css;
6
-
7
- function __construct() {
8
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), 1 );
9
- $this->inline_css = null;
10
- }
11
-
12
- public static function single() {
13
- static $single;
14
-
15
- return empty( $single ) ? $single = new self() : $single;
16
- }
17
-
18
- /**
19
- * Add CSS that needs to go inline.
20
- *
21
- * @param $post_id
22
- * @param $css
23
- */
24
- public function add_inline_css( $post_id, $css ) {
25
- if ( is_null( $this->inline_css ) ) {
26
- // Initialize the inline CSS array and add actions to handle printing.
27
- $this->inline_css = array();
28
- add_action( 'wp_head', array( $this, 'print_inline_css' ), 12 );
29
- add_action( 'wp_footer', array( $this, 'print_inline_css' ) );
30
- }
31
-
32
- $this->inline_css[ $post_id ] = $css;
33
-
34
- // Enqueue the front styles, if they haven't already been enqueued
35
- if ( ! wp_style_is( 'siteorigin-panels-front', 'enqueued' ) ) {
36
- wp_enqueue_style( 'siteorigin-panels-front' );
37
- }
38
- }
39
-
40
- /**
41
- * Generate the CSS for the page layout.
42
- *
43
- * @param $post_id
44
- * @param $panels_data
45
- * @param $layout_data
46
- *
47
- * @return string
48
- */
49
- public function generate_css( $post_id, $panels_data = false, $layout_data = false ) {
50
- // Exit if we don't have panels data
51
- if ( empty( $panels_data ) ) {
52
- $panels_data = get_post_meta( $post_id, 'panels_data', true );
53
- if ( empty( $panels_data ) ) {
54
- return '';
55
- }
56
- }
57
- if ( empty( $layout_data ) ) {
58
- $layout_data = $this->get_panels_layout_data( $panels_data );
59
- $layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
60
- }
61
-
62
- // Get some of the default settings
63
- $settings = siteorigin_panels_setting();
64
- $panels_tablet_width = $settings['tablet-width'];
65
- $panels_mobile_width = $settings['mobile-width'];
66
- $panels_margin_bottom = $settings['margin-bottom'];
67
- $panels_margin_bottom_last_row = $settings['margin-bottom-last-row'];
68
-
69
- $css = new SiteOrigin_Panels_Css_Builder();
70
-
71
- $ci = 0;
72
- foreach ( $layout_data as $ri => $row ) {
73
- if ( empty( $row['cells'] ) ) {
74
- continue;
75
- }
76
-
77
- // Let other themes and plugins change the gutter.
78
- $gutter = apply_filters( 'siteorigin_panels_css_row_gutter', $settings['margin-sides'] . 'px', $row, $ri, $panels_data );
79
- preg_match( '/([0-9\.,]+)(.*)/', $gutter, $gutter_parts );
80
-
81
- $cell_count = count( $row['cells'] );
82
-
83
- // Add the cell sizing
84
- foreach ( $row['cells'] as $ci => $cell ) {
85
- $weight = apply_filters( 'siteorigin_panels_css_cell_weight', $cell['weight'], $row, $ri, $cell, $ci - 1, $panels_data, $post_id );
86
- $rounded_width = round( $weight * 100, 4 ) . '%';
87
- $calc_width = 'calc(' . $rounded_width . ' - ( ' . ( 1 - $weight ) . ' * ' . $gutter . ' ) )';
88
- // Add the width and ensure we have correct formatting for CSS.
89
- $css->add_cell_css( $post_id, $ri, $ci, '', array(
90
- 'width' => array(
91
- // For some locales PHP uses ',' for decimal separation.
92
- // This seems to happen when a plugin calls `setlocale(LC_ALL, 'de_DE');` or `setlocale(LC_NUMERIC, 'de_DE');`
93
- // This should prevent issues with column sizes in these cases.
94
- str_replace( ',', '.', $rounded_width ),
95
- str_replace( ',', '.', $calc_width ),
96
- )
97
- ) );
98
- }
99
-
100
- if (
101
- $ri != count( $layout_data ) - 1 ||
102
- ! empty( $row['style']['bottom_margin'] ) ||
103
- ! empty( $panels_margin_bottom_last_row )
104
- ) {
105
- // Filter the bottom margin for this row with the arguments
106
- $css->add_row_css( $post_id, $ri, '', array(
107
- 'margin-bottom' => apply_filters( 'siteorigin_panels_css_row_margin_bottom', $panels_margin_bottom . 'px', $row, $ri, $panels_data, $post_id )
108
- ) );
109
- }
110
-
111
- $collapse_order = ! empty( $row['style']['collapse_order'] ) ? $row['style']['collapse_order'] : ( ! is_rtl() ? 'left-top' : 'right-top' );
112
-
113
- if ( $settings['responsive'] ) {
114
-
115
- // The default collapse behaviour
116
- if ( empty( $row['style']['collapse_behaviour'] ) ) {
117
-
118
- if (
119
- $settings['tablet-layout'] &&
120
- $cell_count >= 3 &&
121
- $panels_tablet_width > $panels_mobile_width
122
- ) {
123
- // Tablet responsive css for the row
124
-
125
- $css->add_row_css( $post_id, $ri, array(
126
- '.panel-no-style',
127
- '.panel-has-style > .panel-row-style'
128
- ), array(
129
- '-ms-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
130
- '-webkit-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
131
- 'flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
132
- ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
133
-
134
- $css->add_cell_css( $post_id, $ri, false, '', array(
135
- '-ms-flex' => '0 1 50%',
136
- '-webkit-flex' => '0 1 50%',
137
- 'flex' => '0 1 50%',
138
- 'margin-right' => '0',
139
- 'margin-bottom' => $panels_margin_bottom . 'px',
140
- ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
141
-
142
-
143
- $remove_bottom_margin = ':nth-';
144
- if ( $collapse_order == 'left-top' ) {
145
- $remove_bottom_margin .= 'last-child(' . ( count( $row['cells'] ) % 2 == 0 ? '-n+2' : '1' ) . ')';
146
- } else {
147
- $remove_bottom_margin .= 'child(-n+2)';
148
- }
149
-
150
- $css->add_cell_css( $post_id, $ri, false, $remove_bottom_margin, array(
151
- 'margin-bottom' => 0,
152
- ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 )
153
- );
154
-
155
- if ( ! empty( $gutter_parts[1] ) ) {
156
- // Tablet responsive css for cells
157
-
158
- $css->add_cell_css( $post_id, $ri, false, ':nth-child(even)', array(
159
- 'padding-left' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
160
- ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
161
-
162
- $css->add_cell_css( $post_id, $ri, false, ':nth-child(odd)', array(
163
- 'padding-right' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
164
- ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
165
- }
166
-
167
- }
168
-
169
- // Mobile Responsive
170
- $css->add_row_css( $post_id, $ri, array(
171
- '.panel-no-style',
172
- '.panel-has-style > .panel-row-style'
173
- ), array(
174
- '-webkit-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
175
- '-ms-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
176
- 'flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
177
- ), $panels_mobile_width );
178
-
179
- $css->add_cell_css( $post_id, $ri, false, '', array(
180
- 'margin-right' => 0,
181
- ), $panels_mobile_width );
182
- }
183
-
184
- $css->add_cell_css( $post_id, $ri, false, '', array(
185
- 'width' => '100%',
186
- ), $panels_mobile_width );
187
-
188
- foreach ( $row['cells'] as $ci => $cell ) {
189
- if ( ( $collapse_order == 'left-top' && $ci != $cell_count - 1 ) || ( $collapse_order == 'right-top' && $ci !== 0 ) ) {
190
- $css->add_cell_css( $post_id, $ri, $ci, '', array(
191
- 'margin-bottom' => $panels_margin_bottom . 'px',
192
- ), $panels_mobile_width );
193
- }
194
- }
195
- }
196
-
197
- }
198
-
199
- // Add the bottom margins
200
- $css->add_widget_css( $post_id, false, false, false, '', array(
201
- 'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_margin_bottom', $panels_margin_bottom . 'px', false, false, $panels_data, $post_id )
202
- ) );
203
- $css->add_widget_css( $post_id, false, false, false, ':last-child', array(
204
- 'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_last_margin_bottom', '0px', false, false, $panels_data, $post_id )
205
- ) );
206
-
207
- if ( $settings['responsive'] ) {
208
- $css->add_cell_css( $post_id, false, false, '', array(
209
- 'padding' => 0,
210
- ), $panels_mobile_width );
211
-
212
- // Hide empty cells on mobile
213
- $css->add_row_css( $post_id, false, ' .panel-grid-cell-empty', array(
214
- 'display' => 'none',
215
- ), $panels_mobile_width );
216
-
217
- // Hide empty cells on mobile
218
- $css->add_row_css( $post_id, false, ' .panel-grid-cell-mobile-last', array(
219
- 'margin-bottom' => '0px',
220
- ), $panels_mobile_width );
221
- }
222
-
223
- // Let other plugins and components filter the CSS object.
224
- $css = apply_filters( 'siteorigin_panels_css_object', $css, $panels_data, $post_id, $layout_data );
225
-
226
- return $css->get_css();
227
- }
228
-
229
- /**
230
- * Render the panels.
231
- *
232
- * @param int|string|bool $post_id The Post ID or 'home'.
233
- * @param bool $enqueue_css Should we also enqueue the layout CSS.
234
- * @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
235
- * @param array $layout_data Reformatted panels_data that includes data about the render.
236
- *
237
- * @return string
238
- */
239
- function render( $post_id = false, $enqueue_css = true, $panels_data = false, & $layout_data = array() ) {
240
-
241
- if ( empty( $post_id ) ) {
242
- $post_id = get_the_ID();
243
- }
244
-
245
- global $siteorigin_panels_current_post;
246
- $old_current_post = $siteorigin_panels_current_post;
247
- $siteorigin_panels_current_post = $post_id;
248
-
249
- // Try get the cached panel from in memory cache.
250
- global $siteorigin_panels_cache;
251
- if ( ! empty( $siteorigin_panels_cache ) && ! empty( $siteorigin_panels_cache[ $post_id ] ) ) {
252
- return $siteorigin_panels_cache[ $post_id ];
253
- }
254
-
255
- if ( empty( $panels_data ) ) {
256
- $panels_data = $this->get_panels_data_for_post( $post_id );
257
- if ( $panels_data === false ) {
258
- return false;
259
- }
260
- }
261
-
262
- $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post_id );
263
- if ( empty( $panels_data ) || empty( $panels_data['grids'] ) ) {
264
- return '';
265
- }
266
-
267
- $layout_data = $this->get_panels_layout_data( $panels_data );
268
- $layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
269
-
270
- ob_start();
271
-
272
- // Add the panel layout wrapper
273
- $layout_classes = apply_filters( 'siteorigin_panels_layout_classes', array( 'panel-layout' ), $post_id, $panels_data );
274
- if ( is_rtl() ) {
275
- $layout_classes[] = 'panel-is-rtl';
276
- }
277
- $layout_attributes = apply_filters( 'siteorigin_panels_layout_attributes', array(
278
- 'id' => 'pl-' . $post_id,
279
- 'class' => implode( ' ', $layout_classes ),
280
- ), $post_id, $panels_data );
281
-
282
- $this->render_element( 'div', $layout_attributes );
283
-
284
- echo apply_filters( 'siteorigin_panels_before_content', '', $panels_data, $post_id );
285
-
286
- foreach ( $layout_data as $ri => & $row ) {
287
- $this->render_row( $post_id, $ri, $row, $panels_data );
288
- }
289
-
290
- echo apply_filters( 'siteorigin_panels_after_content', '', $panels_data, $post_id );
291
-
292
- echo '</div>';
293
-
294
- do_action( 'siteorigin_panels_after_render', $panels_data, $post_id );
295
-
296
- $html = ob_get_clean();
297
-
298
- if ( $enqueue_css && ! isset( $this->inline_css[ $post_id ] ) ) {
299
- wp_enqueue_style( 'siteorigin-panels-front' );
300
- $this->add_inline_css( $post_id, $this->generate_css( $post_id, $panels_data, $layout_data ) );
301
- }
302
-
303
- // Reset the current post
304
- $siteorigin_panels_current_post = $old_current_post;
305
-
306
- return apply_filters( 'siteorigin_panels_render', $html, $post_id, ! empty( $post ) ? $post : null );
307
- }
308
-
309
- /**
310
- * Echo the style wrapper and return if there was a wrapper
311
- *
312
- * @param string $name The name of the style wrapper
313
- * @param array $style The style wrapper args. Used as an argument for siteorigin_panels_{$name}_style_attributes
314
- * @param string|bool $for An identifier of what this style wrapper is for
315
- *
316
- * @return bool Is there a style wrapper
317
- */
318
- private function start_style_wrapper( $name, $style = array(), $for = false ) {
319
- $attributes = array();
320
-
321
- if ( empty( $attributes['class'] ) ) {
322
- $attributes['class'] = array();
323
- }
324
- if ( empty( $attributes['style'] ) ) {
325
- $attributes['style'] = '';
326
- }
327
-
328
- // Get everything related to the style wrapper
329
- $attributes = apply_filters( 'siteorigin_panels_' . $name . '_style_attributes', $attributes, $style );
330
- $attributes = apply_filters( 'siteorigin_panels_general_style_attributes', $attributes, $style );
331
-
332
- $standard_css = array();
333
- $standard_css = apply_filters( 'siteorigin_panels_' . $name . '_style_css', $standard_css, $style );
334
- $standard_css = apply_filters( 'siteorigin_panels_general_style_css', $standard_css, $style );
335
-
336
- $mobile_css = array();
337
- $mobile_css = apply_filters( 'siteorigin_panels_' . $name . '_style_mobile_css', $mobile_css, $style );
338
- $mobile_css = apply_filters( 'siteorigin_panels_general_style_mobile_css', $mobile_css, $style );
339
-
340
- // Remove anything we didn't actually use
341
- if ( empty( $attributes['class'] ) ) {
342
- unset( $attributes['class'] );
343
- }
344
- if ( empty( $attributes['style'] ) ) {
345
- unset( $attributes['style'] );
346
- }
347
-
348
- $style_wrapper = '';
349
- if ( ! empty( $attributes ) || ! empty( $standard_css ) || ! empty( $mobile_css ) ) {
350
- if ( empty( $attributes['class'] ) ) {
351
- $attributes['class'] = array();
352
- }
353
- $attributes['class'][] = 'panel-' . $name . '-style';
354
- if ( ! empty( $for ) ) {
355
- $attributes['class'][] = 'panel-' . $name . '-style-for-' . sanitize_html_class( $for );
356
- }
357
- $attributes['class'] = array_unique( $attributes['class'] );
358
-
359
- // Filter and sanitize the classes
360
- $attributes['class'] = apply_filters( 'siteorigin_panels_' . $name . '_style_classes', $attributes['class'], $attributes, $style );
361
- $attributes['class'] = array_map( 'sanitize_html_class', $attributes['class'] );
362
-
363
- $style_wrapper = '<div ';
364
- foreach ( $attributes as $name => $value ) {
365
- // Attributes start with _ are used for internal communication between filters, so are not added to the HTML
366
- // We don't make use of this in our styling, so its left as a mechanism for other plugins.
367
- if ( substr( $name, 0, 1 ) === '_' ) {
368
- continue;
369
- }
370
-
371
- if ( is_array( $value ) ) {
372
- $style_wrapper .= $name . '="' . esc_attr( implode( " ", array_unique( $value ) ) ) . '" ';
373
- } else {
374
- $style_wrapper .= $name . '="' . esc_attr( $value ) . '" ';
375
- }
376
- }
377
- $style_wrapper .= '>';
378
-
379
- return $style_wrapper;
380
- }
381
-
382
- return $style_wrapper;
383
- }
384
-
385
- /**
386
- * Render the widget.
387
- *
388
- * @param array $widget_info The widget info.
389
- * @param array $instance The widget instance
390
- * @param int $grid_index The grid index.
391
- * @param int $cell_index The cell index.
392
- * @param int $widget_index The index of this widget.
393
- * @param bool $is_first Is this the first widget in the cell.
394
- * @param bool $is_last Is this the last widget in the cell.
395
- * @param bool $post_id
396
- * @param string $style_wrapper The start of the style wrapper
397
- */
398
- function the_widget( $widget_info, $instance, $grid_index, $cell_index, $widget_index, $is_first, $is_last, $post_id = false, $style_wrapper = '' ) {
399
-
400
- global $wp_widget_factory;
401
-
402
- // Set widget class to $widget
403
- $widget_class = $widget_info['class'];
404
- $widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
405
-
406
- // Load the widget from the widget factory and give themes and plugins a chance to provide their own
407
- $the_widget = ! empty( $wp_widget_factory->widgets[ $widget_class ] ) ? $wp_widget_factory->widgets[ $widget_class ] : false;
408
- $the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget_class, $instance );
409
-
410
- if ( empty( $post_id ) ) {
411
- $post_id = get_the_ID();
412
- }
413
-
414
- $classes = array( 'so-panel' );
415
- if ( siteorigin_panels_setting( 'add-widget-class' ) ) {
416
- $classes[] = 'widget';
417
- }
418
- if ( ! empty( $the_widget ) && ! empty( $the_widget->id_base ) ) {
419
- $classes[] = 'widget_' . $the_widget->id_base;
420
- }
421
- if ( ! empty( $the_widget ) && is_array( $the_widget->widget_options ) && ! empty( $the_widget->widget_options['classname'] ) ) {
422
- $classes[] = $the_widget->widget_options['classname'];
423
- }
424
- if ( $is_first ) {
425
- $classes[] = 'panel-first-child';
426
- }
427
- if ( $is_last ) {
428
- $classes[] = 'panel-last-child';
429
- }
430
- $id = 'panel-' . $post_id . '-' . $grid_index . '-' . $cell_index . '-' . $widget_index;
431
-
432
- // Filter and sanitize the classes
433
- $classes = apply_filters( 'siteorigin_panels_widget_classes', $classes, $widget_class, $instance, $widget_info );
434
- $classes = explode( ' ', implode( ' ', $classes ) );
435
- $classes = array_filter( $classes );
436
- $classes = array_unique( $classes );
437
- $classes = array_map( 'sanitize_html_class', $classes );
438
-
439
- $title_html = siteorigin_panels_setting( 'title-html' );
440
- if ( strpos( $title_html, '{{title}}' ) !== false ) {
441
- list( $before_title, $after_title ) = explode( '{{title}}', $title_html, 2 );
442
- } else {
443
- $before_title = '<h3 class="widget-title">';
444
- $after_title = '</h3>';
445
- }
446
-
447
- // Attributes of the widget wrapper
448
- $attributes = apply_filters( 'siteorigin_panels_widget_attributes', array(
449
- 'id' => $id,
450
- 'class' => implode( ' ', $classes ),
451
- 'data-index' => $widget_info['widget_index'],
452
- ), $widget_info );
453
-
454
- $before_widget = '<div ';
455
- foreach ( $attributes as $k => $v ) {
456
- $before_widget .= esc_attr( $k ) . '="' . esc_attr( $v ) . '" ';
457
- }
458
- $before_widget .= '>';
459
-
460
- $args = array(
461
- 'before_widget' => $before_widget,
462
- 'after_widget' => '</div>',
463
- 'before_title' => $before_title,
464
- 'after_title' => $after_title,
465
- 'widget_id' => 'widget-' . $grid_index . '-' . $cell_index . '-' . $widget_index
466
- );
467
-
468
- // Let other themes and plugins change the arguments that go to the widget class.
469
- $args = apply_filters( 'siteorigin_panels_widget_args', $args );
470
-
471
- // If there is a style wrapper, add it.
472
- if ( ! empty( $style_wrapper ) ) {
473
- $args['before_widget'] = $args['before_widget'] . $style_wrapper;
474
- $args['after_widget'] = '</div>' . $args['after_widget'];
475
- }
476
-
477
- // This gives other plugins the chance to take over rendering of widgets
478
- $widget_html = apply_filters( 'siteorigin_panels_the_widget_html', '', $the_widget, $args, $instance );
479
-
480
- if ( ! empty( $widget_html ) ) {
481
- echo $args['before_widget'];
482
- echo $widget_html;
483
- echo $args['after_widget'];
484
- } else if ( ! empty( $the_widget ) && is_a( $the_widget, 'WP_Widget' ) ) {
485
- $the_widget->widget( $args, $instance );
486
- } else {
487
- // This gives themes a chance to display some sort of placeholder for missing widgets
488
- echo apply_filters( 'siteorigin_panels_missing_widget', $args['before_widget'] . $args['after_widget'], $widget_class, $args, $instance );
489
- }
490
- }
491
-
492
- /**
493
- * Print inline CSS in the header and footer.
494
- */
495
- function print_inline_css() {
496
- if ( ! empty( $this->inline_css ) ) {
497
- $the_css = '';
498
- foreach ( $this->inline_css as $post_id => $css ) {
499
- if ( empty( $css ) ) {
500
- continue;
501
- }
502
- $the_css .= '/* Layout ' . esc_attr( $post_id ) . ' */ ';
503
- $the_css .= $css;
504
- }
505
-
506
- // Reset the inline CSS
507
- $this->inline_css = null;
508
-
509
- switch ( current_filter() ) {
510
- case 'wp_head' :
511
- $css_id = 'head';
512
- break;
513
-
514
- case 'wp_footer' :
515
- $css_id = 'footer';
516
- break;
517
-
518
- default :
519
- $css_id = sanitize_html_class( current_filter() );
520
- break;
521
- }
522
-
523
- // Allow third party developers to change the inline styles or remove them completely.
524
- $the_css = apply_filters( 'siteorigin_panels_inline_styles', $the_css );
525
-
526
- if ( ! empty( $the_css ) ) {
527
- ?>
528
- <style type="text/css" media="all"
529
- id="siteorigin-panels-layouts-<?php echo esc_attr( $css_id ) ?>"><?php echo $the_css ?></style><?php
530
- }
531
- }
532
- }
533
-
534
- /**
535
- * Enqueue the required styles
536
- */
537
- function enqueue_styles() {
538
- // Register the style to support possible lazy loading
539
- wp_register_style( 'siteorigin-panels-front', SiteOrigin_Panels::front_css_url(), array(), SITEORIGIN_PANELS_VERSION );
540
- }
541
-
542
- /**
543
- * Retrieve panels data for a post or a prebuilt layout or the home page layout.
544
- *
545
- * @param string $post_id
546
- *
547
- * @return array
548
- */
549
- private function get_panels_data_for_post( $post_id ) {
550
- if ( strpos( $post_id, 'prebuilt:' ) === 0 ) {
551
- list( $null, $prebuilt_id ) = explode( ':', $post_id, 2 );
552
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
553
- $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : array();
554
- } else if ( $post_id == 'home' ) {
555
- $page_id = get_option( 'page_on_front' );
556
- if ( empty( $page_id ) ) {
557
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
558
- }
559
-
560
- $panels_data = ! empty( $page_id ) ? get_post_meta( $page_id, 'panels_data', true ) : null;
561
-
562
- if ( is_null( $panels_data ) ) {
563
- // Load the default layout
564
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
565
- $prebuilt_id = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
566
-
567
- $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : current( $layouts );
568
- }
569
- } else {
570
- if ( post_password_required( $post_id ) ) {
571
- return false;
572
- }
573
- $panels_data = get_post_meta( $post_id, 'panels_data', true );
574
- }
575
-
576
- return $panels_data;
577
- }
578
-
579
- /**
580
- * Transform flat panels data into a hierarchical structure.
581
- *
582
- * @param array $panels_data Flat panels data containing `grids`, `grid_cells`, and `widgets`.
583
- *
584
- * @return array Hierarchical structure of rows => cells => widgets.
585
- */
586
- public function get_panels_layout_data( $panels_data ) {
587
- $layout_data = array();
588
-
589
- foreach ( $panels_data['grids'] as $grid ) {
590
- $layout_data[] = array(
591
- 'style' => ! empty( $grid['style'] ) ? $grid['style'] : array(),
592
- 'ratio' => ! empty( $grid['ratio'] ) ? $grid['ratio'] : '',
593
- 'ratio_direction' => ! empty( $grid['ratio_direction'] ) ? $grid['ratio_direction'] : '',
594
- 'color_label' => ! empty( $grid['color_label'] ) ? $grid['color_label'] : '',
595
- 'label' => ! empty( $grid['label'] ) ? $grid['label'] : '',
596
- 'cells' => array()
597
- );
598
- }
599
-
600
- foreach ( $panels_data['grid_cells'] as $cell ) {
601
- $layout_data[ $cell['grid'] ]['cells'][] = array(
602
- 'widgets' => array(),
603
- 'style' => ! empty( $cell['style'] ) ? $cell['style'] : array(),
604
- 'weight' => floatval( $cell['weight'] ),
605
- );
606
- }
607
-
608
- foreach ( $panels_data['widgets'] as $i => $widget ) {
609
- $widget['panels_info']['widget_index'] = $i;
610
- $row_index = intval( $widget['panels_info']['grid'] );
611
- $cell_index = intval( $widget['panels_info']['cell'] );
612
- $layout_data[ $row_index ]['cells'][ $cell_index ]['widgets'][] = $widget;
613
- }
614
-
615
- return $layout_data;
616
- }
617
-
618
- /**
619
- * Outputs the given HTML tag with the given attributes.
620
- *
621
- * @param string $tag The HTML element to render.
622
- * @param array $attributes The attributes for the HTML element.
623
- *
624
- */
625
- private function render_element( $tag, $attributes ) {
626
-
627
- echo '<' . $tag;
628
- foreach ( $attributes as $name => $value ) {
629
- if ( $value ) {
630
- echo ' ' . $name . '="' . esc_attr( $value ) . '" ';
631
- }
632
- }
633
- echo '>';
634
-
635
- }
636
-
637
- /**
638
- * Render everything for the given row, including:
639
- * - filters before and after row,
640
- * - row style wrapper,
641
- * - row element wrapper with attributes,
642
- * - child cells
643
- *
644
- * @param string $post_id The ID of the post containing this layout.
645
- * @param int $ri The index of this row.
646
- * @param array $row The model containing this row's data and child cells.
647
- * @param array $panels_data A copy of panels_data for filters.
648
- *
649
- */
650
- private function render_row( $post_id, $ri, & $row, & $panels_data ) {
651
- $row_style_wrapper = $this->start_style_wrapper( 'row', ! empty( $row['style'] ) ? $row['style'] : array(), $post_id . '-' . $ri );
652
-
653
- $row_classes = array( 'panel-grid' );
654
- $row_classes[] = ! empty( $row_style_wrapper ) ? 'panel-has-style' : 'panel-no-style';
655
- $row_classes = apply_filters( 'siteorigin_panels_row_classes', $row_classes, $row );
656
-
657
- $row_attributes = apply_filters( 'siteorigin_panels_row_attributes', array(
658
- 'id' => 'pg-' . $post_id . '-' . $ri,
659
- 'class' => implode( ' ', $row_classes ),
660
- ), $row );
661
-
662
- // This allows other themes and plugins to add html before the row
663
- echo apply_filters( 'siteorigin_panels_before_row', '', $row, $row_attributes );
664
-
665
- $this->render_element( 'div', $row_attributes );
666
-
667
- if ( ! empty( $row_style_wrapper ) ) {
668
- echo $row_style_wrapper;
669
- }
670
-
671
- foreach ( $row['cells'] as $ci => & $cell ) {
672
- $this->render_cell( $post_id, $ri, $ci, $cell, $row['cells'], $panels_data );
673
- }
674
-
675
- // Close the style wrapper
676
- if ( ! empty( $row_style_wrapper ) ) {
677
- echo '</div>';
678
- }
679
-
680
- echo '</div>';
681
-
682
- // This allows other themes and plugins to add html after the row
683
- echo apply_filters( 'siteorigin_panels_after_row', '', $row, $row_attributes );
684
-
685
- }
686
-
687
- /**
688
- *
689
- * Render everything for the given cell, including:
690
- * - filters before and after cell,
691
- * - cell element wrapper with attributes,
692
- * - style wrapper,
693
- * - child widgets
694
- *
695
- * @param string $post_id The ID of the post containing this layout.
696
- * @param int $ri The index of this cell's parent row.
697
- * @param int $ci The index of this cell.
698
- * @param array $cell The model containing this cell's data and child widgets.
699
- * @param array $cells The array of cells containing this cell.
700
- * @param array $panels_data A copy of panels_data for filters
701
- */
702
- private function render_cell( $post_id, $ri, $ci, & $cell, $cells, & $panels_data ) {
703
-
704
- $cell_classes = array( 'panel-grid-cell' );
705
-
706
- if ( empty( $cell['widgets'] ) ) {
707
- $cell_classes[] = 'panel-grid-cell-empty';
708
- }
709
-
710
- if ( $ci == count( $cells ) - 2 && count( $cells[ $ci + 1 ]['widgets'] ) == 0 ) {
711
- $cell_classes[] = 'panel-grid-cell-mobile-last';
712
- }
713
-
714
- // Themes can add their own styles to cells
715
- $cell_classes = apply_filters( 'siteorigin_panels_cell_classes', $cell_classes, $cell );
716
-
717
- // Legacy filter, use `siteorigin_panels_cell_classes` instead
718
- $cell_classes = apply_filters( 'siteorigin_panels_row_cell_classes', $cell_classes, $panels_data, $cell );
719
-
720
- $cell_attributes = apply_filters( 'siteorigin_panels_cell_attributes', array(
721
- 'id' => 'pgc-' . $post_id . '-' . $ri . '-' . $ci,
722
- 'class' => implode( ' ', $cell_classes ),
723
- ), $cell );
724
-
725
- // Legacy filter, use `siteorigin_panels_cell_attributes` instead
726
- $cell_attributes = apply_filters( 'siteorigin_panels_row_cell_attributes', $cell_attributes, $panels_data, $cell );
727
-
728
- echo apply_filters( 'siteorigin_panels_before_cell', '', $cell, $cell_attributes );
729
-
730
- $this->render_element( 'div', $cell_attributes );
731
-
732
- $grid = $panels_data['grids'][ $ri ];
733
-
734
- if ( empty( $cell['style']['class'] ) && ! empty( $grid['style']['cell_class'] ) ) {
735
- $cell['style']['class'] = $grid['style']['cell_class'];
736
- }
737
-
738
- $cell_style = ! empty( $cell['style'] ) ? $cell['style'] : array();
739
- $cell_style_wrapper = $this->start_style_wrapper( 'cell', $cell_style, $post_id . '-' . $ri . '-' . $ci );
740
- if ( ! empty( $cell_style_wrapper ) ) {
741
- echo $cell_style_wrapper;
742
- }
743
-
744
- foreach ( $cell['widgets'] as $wi => & $widget ) {
745
- $is_last = ( $wi == count( $cell['widgets'] ) - 1 );
746
- $this->render_widget( $post_id, $ri, $ci, $wi, $widget, $is_last );
747
- }
748
-
749
- if ( ! empty( $cell_style_wrapper ) ) {
750
- echo '</div>';
751
- }
752
- echo '</div>';
753
-
754
- echo apply_filters( 'siteorigin_panels_after_cell', '', $cell, $cell_attributes );
755
- }
756
-
757
- /**
758
- *
759
- * Gets the style wrapper for this widget and passes it through to `the_widget` along with other required parameters.
760
- *
761
- * @param string $post_id The ID of the post containing this layout.
762
- * @param int $ri The index of this widget's ancestor row.
763
- * @param int $ci The index of this widget's parent cell.
764
- * @param int $wi The index of this widget.
765
- * @param array $widget The model containing this widget's data.
766
- * @param bool $is_last Whether this is the last widget in the parent cell.
767
- *
768
- */
769
- private function render_widget( $post_id, $ri, $ci, $wi, & $widget, $is_last ) {
770
-
771
- $widget_style_wrapper = $this->start_style_wrapper(
772
- 'widget',
773
- ! empty( $widget['panels_info']['style'] ) ? $widget['panels_info']['style'] : array(),
774
- $post_id . '-' . $ri . '-' . $ci . '-' . $wi
775
- );
776
-
777
- $this->the_widget(
778
- $widget['panels_info'],
779
- $widget,
780
- $ri,
781
- $ci,
782
- $wi,
783
- $wi == 0,
784
- $is_last,
785
- $post_id,
786
- $widget_style_wrapper
787
- );
788
-
789
- }
790
-
791
- public function front_css_url() {
792
- return siteorigin_panels_url( 'css/front-flex.css' );
793
- }
794
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Renderer {
4
+
5
+ private $inline_css;
6
+
7
+ function __construct() {
8
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_styles' ), 1 );
9
+ $this->inline_css = null;
10
+ }
11
+
12
+ public static function single() {
13
+ static $single;
14
+
15
+ return empty( $single ) ? $single = new self() : $single;
16
+ }
17
+
18
+ /**
19
+ * Add CSS that needs to go inline.
20
+ *
21
+ * @param $post_id
22
+ * @param $css
23
+ */
24
+ public function add_inline_css( $post_id, $css ) {
25
+ if ( is_null( $this->inline_css ) ) {
26
+ // Initialize the inline CSS array and add actions to handle printing.
27
+ $this->inline_css = array();
28
+ add_action( 'wp_head', array( $this, 'print_inline_css' ), 12 );
29
+ add_action( 'wp_footer', array( $this, 'print_inline_css' ) );
30
+ }
31
+
32
+ $this->inline_css[ $post_id ] = $css;
33
+
34
+ // Enqueue the front styles, if they haven't already been enqueued
35
+ if ( ! wp_style_is( 'siteorigin-panels-front', 'enqueued' ) ) {
36
+ wp_enqueue_style( 'siteorigin-panels-front' );
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Generate the CSS for the page layout.
42
+ *
43
+ * @param $post_id
44
+ * @param $panels_data
45
+ * @param $layout_data
46
+ *
47
+ * @return string
48
+ */
49
+ public function generate_css( $post_id, $panels_data = false, $layout_data = false ) {
50
+ // Exit if we don't have panels data
51
+ if ( empty( $panels_data ) ) {
52
+ $panels_data = get_post_meta( $post_id, 'panels_data', true );
53
+ if ( empty( $panels_data ) ) {
54
+ return '';
55
+ }
56
+ }
57
+ if ( empty( $layout_data ) ) {
58
+ $layout_data = $this->get_panels_layout_data( $panels_data );
59
+ $layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
60
+ }
61
+
62
+ // Get some of the default settings
63
+ $settings = siteorigin_panels_setting();
64
+ $panels_tablet_width = $settings['tablet-width'];
65
+ $panels_mobile_width = $settings['mobile-width'];
66
+ $panels_margin_bottom = $settings['margin-bottom'];
67
+ $panels_margin_bottom_last_row = $settings['margin-bottom-last-row'];
68
+
69
+ $css = new SiteOrigin_Panels_Css_Builder();
70
+
71
+ $ci = 0;
72
+ foreach ( $layout_data as $ri => $row ) {
73
+ if ( empty( $row['cells'] ) ) {
74
+ continue;
75
+ }
76
+
77
+ // Let other themes and plugins change the gutter.
78
+ $gutter = apply_filters( 'siteorigin_panels_css_row_gutter', $settings['margin-sides'] . 'px', $row, $ri, $panels_data );
79
+ preg_match( '/([0-9\.,]+)(.*)/', $gutter, $gutter_parts );
80
+
81
+ $cell_count = count( $row['cells'] );
82
+
83
+ // Add the cell sizing
84
+ foreach ( $row['cells'] as $ci => $cell ) {
85
+ $weight = apply_filters( 'siteorigin_panels_css_cell_weight', $cell['weight'], $row, $ri, $cell, $ci - 1, $panels_data, $post_id );
86
+ $rounded_width = round( $weight * 100, 4 ) . '%';
87
+ $calc_width = 'calc(' . $rounded_width . ' - ( ' . ( 1 - $weight ) . ' * ' . $gutter . ' ) )';
88
+ // Add the width and ensure we have correct formatting for CSS.
89
+ $css->add_cell_css( $post_id, $ri, $ci, '', array(
90
+ 'width' => array(
91
+ // For some locales PHP uses ',' for decimal separation.
92
+ // This seems to happen when a plugin calls `setlocale(LC_ALL, 'de_DE');` or `setlocale(LC_NUMERIC, 'de_DE');`
93
+ // This should prevent issues with column sizes in these cases.
94
+ str_replace( ',', '.', $rounded_width ),
95
+ str_replace( ',', '.', $calc_width ),
96
+ )
97
+ ) );
98
+ }
99
+
100
+ if (
101
+ $ri != count( $layout_data ) - 1 ||
102
+ ! empty( $row['style']['bottom_margin'] ) ||
103
+ ! empty( $panels_margin_bottom_last_row )
104
+ ) {
105
+ // Filter the bottom margin for this row with the arguments
106
+ $css->add_row_css( $post_id, $ri, '', array(
107
+ 'margin-bottom' => apply_filters( 'siteorigin_panels_css_row_margin_bottom', $panels_margin_bottom . 'px', $row, $ri, $panels_data, $post_id )
108
+ ) );
109
+ }
110
+
111
+ $collapse_order = ! empty( $row['style']['collapse_order'] ) ? $row['style']['collapse_order'] : ( ! is_rtl() ? 'left-top' : 'right-top' );
112
+
113
+ if ( $settings['responsive'] ) {
114
+
115
+ // The default collapse behaviour
116
+ if ( empty( $row['style']['collapse_behaviour'] ) ) {
117
+
118
+ if (
119
+ $settings['tablet-layout'] &&
120
+ $cell_count >= 3 &&
121
+ $panels_tablet_width > $panels_mobile_width
122
+ ) {
123
+ // Tablet responsive css for the row
124
+
125
+ $css->add_row_css( $post_id, $ri, array(
126
+ '.panel-no-style',
127
+ '.panel-has-style > .panel-row-style'
128
+ ), array(
129
+ '-ms-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
130
+ '-webkit-flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
131
+ 'flex-wrap' => $collapse_order == 'left-top' ? 'wrap' : 'wrap-reverse',
132
+ ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
133
+
134
+ $css->add_cell_css( $post_id, $ri, false, '', array(
135
+ '-ms-flex' => '0 1 50%',
136
+ '-webkit-flex' => '0 1 50%',
137
+ 'flex' => '0 1 50%',
138
+ 'margin-right' => '0',
139
+ 'margin-bottom' => $panels_margin_bottom . 'px',
140
+ ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
141
+
142
+
143
+ $remove_bottom_margin = ':nth-';
144
+ if ( $collapse_order == 'left-top' ) {
145
+ $remove_bottom_margin .= 'last-child(' . ( count( $row['cells'] ) % 2 == 0 ? '-n+2' : '1' ) . ')';
146
+ } else {
147
+ $remove_bottom_margin .= 'child(-n+2)';
148
+ }
149
+
150
+ $css->add_cell_css( $post_id, $ri, false, $remove_bottom_margin, array(
151
+ 'margin-bottom' => 0,
152
+ ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 )
153
+ );
154
+
155
+ if ( ! empty( $gutter_parts[1] ) ) {
156
+ // Tablet responsive css for cells
157
+
158
+ $css->add_cell_css( $post_id, $ri, false, ':nth-child(even)', array(
159
+ 'padding-left' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
160
+ ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
161
+
162
+ $css->add_cell_css( $post_id, $ri, false, ':nth-child(odd)', array(
163
+ 'padding-right' => ( floatval( $gutter_parts[1] / 2 ) . $gutter_parts[2] ),
164
+ ), $panels_tablet_width . ':' . ( $panels_mobile_width + 1 ) );
165
+ }
166
+
167
+ }
168
+
169
+ // Mobile Responsive
170
+ $css->add_row_css( $post_id, $ri, array(
171
+ '.panel-no-style',
172
+ '.panel-has-style > .panel-row-style'
173
+ ), array(
174
+ '-webkit-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
175
+ '-ms-flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
176
+ 'flex-direction' => $collapse_order == 'left-top' ? 'column' : 'column-reverse',
177
+ ), $panels_mobile_width );
178
+
179
+ $css->add_cell_css( $post_id, $ri, false, '', array(
180
+ 'margin-right' => 0,
181
+ ), $panels_mobile_width );
182
+ }
183
+
184
+ $css->add_cell_css( $post_id, $ri, false, '', array(
185
+ 'width' => '100%',
186
+ ), $panels_mobile_width );
187
+
188
+ foreach ( $row['cells'] as $ci => $cell ) {
189
+ if ( ( $collapse_order == 'left-top' && $ci != $cell_count - 1 ) || ( $collapse_order == 'right-top' && $ci !== 0 ) ) {
190
+ $css->add_cell_css( $post_id, $ri, $ci, '', array(
191
+ 'margin-bottom' => $panels_margin_bottom . 'px',
192
+ ), $panels_mobile_width );
193
+ }
194
+ }
195
+ }
196
+
197
+ }
198
+
199
+ // Add the bottom margins
200
+ $css->add_widget_css( $post_id, false, false, false, '', array(
201
+ 'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_margin_bottom', $panels_margin_bottom . 'px', false, false, $panels_data, $post_id )
202
+ ) );
203
+ $css->add_widget_css( $post_id, false, false, false, ':last-child', array(
204
+ 'margin-bottom' => apply_filters( 'siteorigin_panels_css_cell_last_margin_bottom', '0px', false, false, $panels_data, $post_id )
205
+ ) );
206
+
207
+ if ( $settings['responsive'] ) {
208
+ $css->add_cell_css( $post_id, false, false, '', array(
209
+ 'padding' => 0,
210
+ ), $panels_mobile_width );
211
+
212
+ // Hide empty cells on mobile
213
+ $css->add_row_css( $post_id, false, ' .panel-grid-cell-empty', array(
214
+ 'display' => 'none',
215
+ ), $panels_mobile_width );
216
+
217
+ // Hide empty cells on mobile
218
+ $css->add_row_css( $post_id, false, ' .panel-grid-cell-mobile-last', array(
219
+ 'margin-bottom' => '0px',
220
+ ), $panels_mobile_width );
221
+ }
222
+
223
+ // Let other plugins and components filter the CSS object.
224
+ $css = apply_filters( 'siteorigin_panels_css_object', $css, $panels_data, $post_id, $layout_data );
225
+
226
+ return $css->get_css();
227
+ }
228
+
229
+ /**
230
+ * Render the panels.
231
+ *
232
+ * @param int|string|bool $post_id The Post ID or 'home'.
233
+ * @param bool $enqueue_css Should we also enqueue the layout CSS.
234
+ * @param array|bool $panels_data Existing panels data. By default load from settings or post meta.
235
+ * @param array $layout_data Reformatted panels_data that includes data about the render.
236
+ *
237
+ * @return string
238
+ */
239
+ function render( $post_id = false, $enqueue_css = true, $panels_data = false, & $layout_data = array() ) {
240
+
241
+ if ( empty( $post_id ) ) {
242
+ $post_id = get_the_ID();
243
+ }
244
+
245
+ global $siteorigin_panels_current_post;
246
+ $old_current_post = $siteorigin_panels_current_post;
247
+ $siteorigin_panels_current_post = $post_id;
248
+
249
+ // Try get the cached panel from in memory cache.
250
+ global $siteorigin_panels_cache;
251
+ if ( ! empty( $siteorigin_panels_cache ) && ! empty( $siteorigin_panels_cache[ $post_id ] ) ) {
252
+ return $siteorigin_panels_cache[ $post_id ];
253
+ }
254
+
255
+ if ( empty( $panels_data ) ) {
256
+ $panels_data = $this->get_panels_data_for_post( $post_id );
257
+ if ( $panels_data === false ) {
258
+ return false;
259
+ }
260
+ }
261
+
262
+ $panels_data = apply_filters( 'siteorigin_panels_data', $panels_data, $post_id );
263
+ if ( empty( $panels_data ) || empty( $panels_data['grids'] ) ) {
264
+ return '';
265
+ }
266
+
267
+ $layout_data = $this->get_panels_layout_data( $panels_data );
268
+ $layout_data = apply_filters( 'siteorigin_panels_layout_data', $layout_data, $post_id );
269
+
270
+ ob_start();
271
+
272
+ // Add the panel layout wrapper
273
+ $layout_classes = apply_filters( 'siteorigin_panels_layout_classes', array( 'panel-layout' ), $post_id, $panels_data );
274
+ if ( is_rtl() ) {
275
+ $layout_classes[] = 'panel-is-rtl';
276
+ }
277
+ $layout_attributes = apply_filters( 'siteorigin_panels_layout_attributes', array(
278
+ 'id' => 'pl-' . $post_id,
279
+ 'class' => implode( ' ', $layout_classes ),
280
+ ), $post_id, $panels_data );
281
+
282
+ $this->render_element( 'div', $layout_attributes );
283
+
284
+ echo apply_filters( 'siteorigin_panels_before_content', '', $panels_data, $post_id );
285
+
286
+ foreach ( $layout_data as $ri => & $row ) {
287
+ $this->render_row( $post_id, $ri, $row, $panels_data );
288
+ }
289
+
290
+ echo apply_filters( 'siteorigin_panels_after_content', '', $panels_data, $post_id );
291
+
292
+ echo '</div>';
293
+
294
+ do_action( 'siteorigin_panels_after_render', $panels_data, $post_id );
295
+
296
+ $html = ob_get_clean();
297
+
298
+ if ( $enqueue_css && ! isset( $this->inline_css[ $post_id ] ) ) {
299
+ wp_enqueue_style( 'siteorigin-panels-front' );
300
+ $this->add_inline_css( $post_id, $this->generate_css( $post_id, $panels_data, $layout_data ) );
301
+ }
302
+
303
+ // Reset the current post
304
+ $siteorigin_panels_current_post = $old_current_post;
305
+
306
+ return apply_filters( 'siteorigin_panels_render', $html, $post_id, ! empty( $post ) ? $post : null );
307
+ }
308
+
309
+ /**
310
+ * Echo the style wrapper and return if there was a wrapper
311
+ *
312
+ * @param string $name The name of the style wrapper
313
+ * @param array $style The style wrapper args. Used as an argument for siteorigin_panels_{$name}_style_attributes
314
+ * @param string|bool $for An identifier of what this style wrapper is for
315
+ *
316
+ * @return bool Is there a style wrapper
317
+ */
318
+ private function start_style_wrapper( $name, $style = array(), $for = false ) {
319
+ $attributes = array();
320
+
321
+ if ( empty( $attributes['class'] ) ) {
322
+ $attributes['class'] = array();
323
+ }
324
+ if ( empty( $attributes['style'] ) ) {
325
+ $attributes['style'] = '';
326
+ }
327
+
328
+ // Get everything related to the style wrapper
329
+ $attributes = apply_filters( 'siteorigin_panels_' . $name . '_style_attributes', $attributes, $style );
330
+ $attributes = apply_filters( 'siteorigin_panels_general_style_attributes', $attributes, $style );
331
+
332
+ $standard_css = array();
333
+ $standard_css = apply_filters( 'siteorigin_panels_' . $name . '_style_css', $standard_css, $style );
334
+ $standard_css = apply_filters( 'siteorigin_panels_general_style_css', $standard_css, $style );
335
+
336
+ $mobile_css = array();
337
+ $mobile_css = apply_filters( 'siteorigin_panels_' . $name . '_style_mobile_css', $mobile_css, $style );
338
+ $mobile_css = apply_filters( 'siteorigin_panels_general_style_mobile_css', $mobile_css, $style );
339
+
340
+ // Remove anything we didn't actually use
341
+ if ( empty( $attributes['class'] ) ) {
342
+ unset( $attributes['class'] );
343
+ }
344
+ if ( empty( $attributes['style'] ) ) {
345
+ unset( $attributes['style'] );
346
+ }
347
+
348
+ $style_wrapper = '';
349
+ if ( ! empty( $attributes ) || ! empty( $standard_css ) || ! empty( $mobile_css ) ) {
350
+ if ( empty( $attributes['class'] ) ) {
351
+ $attributes['class'] = array();
352
+ }
353
+ $attributes['class'][] = 'panel-' . $name . '-style';
354
+ if ( ! empty( $for ) ) {
355
+ $attributes['class'][] = 'panel-' . $name . '-style-for-' . sanitize_html_class( $for );
356
+ }
357
+ $attributes['class'] = array_unique( $attributes['class'] );
358
+
359
+ // Filter and sanitize the classes
360
+ $attributes['class'] = apply_filters( 'siteorigin_panels_' . $name . '_style_classes', $attributes['class'], $attributes, $style );
361
+ $attributes['class'] = array_map( 'sanitize_html_class', $attributes['class'] );
362
+
363
+ $style_wrapper = '<div ';
364
+ foreach ( $attributes as $name => $value ) {
365
+ // Attributes start with _ are used for internal communication between filters, so are not added to the HTML
366
+ // We don't make use of this in our styling, so its left as a mechanism for other plugins.
367
+ if ( substr( $name, 0, 1 ) === '_' ) {
368
+ continue;
369
+ }
370
+
371
+ if ( is_array( $value ) ) {
372
+ $style_wrapper .= $name . '="' . esc_attr( implode( " ", array_unique( $value ) ) ) . '" ';
373
+ } else {
374
+ $style_wrapper .= $name . '="' . esc_attr( $value ) . '" ';
375
+ }
376
+ }
377
+ $style_wrapper .= '>';
378
+
379
+ return $style_wrapper;
380
+ }
381
+
382
+ return $style_wrapper;
383
+ }
384
+
385
+ /**
386
+ * Render the widget.
387
+ *
388
+ * @param array $widget_info The widget info.
389
+ * @param array $instance The widget instance
390
+ * @param int $grid_index The grid index.
391
+ * @param int $cell_index The cell index.
392
+ * @param int $widget_index The index of this widget.
393
+ * @param bool $is_first Is this the first widget in the cell.
394
+ * @param bool $is_last Is this the last widget in the cell.
395
+ * @param bool $post_id
396
+ * @param string $style_wrapper The start of the style wrapper
397
+ */
398
+ function the_widget( $widget_info, $instance, $grid_index, $cell_index, $widget_index, $is_first, $is_last, $post_id = false, $style_wrapper = '' ) {
399
+
400
+ global $wp_widget_factory;
401
+
402
+ // Set widget class to $widget
403
+ $widget_class = $widget_info['class'];
404
+ $widget_class = apply_filters( 'siteorigin_panels_widget_class', $widget_class );
405
+
406
+ // Load the widget from the widget factory and give themes and plugins a chance to provide their own
407
+ $the_widget = ! empty( $wp_widget_factory->widgets[ $widget_class ] ) ? $wp_widget_factory->widgets[ $widget_class ] : false;
408
+ $the_widget = apply_filters( 'siteorigin_panels_widget_object', $the_widget, $widget_class, $instance );
409
+
410
+ if ( empty( $post_id ) ) {
411
+ $post_id = get_the_ID();
412
+ }
413
+
414
+ $classes = array( 'so-panel' );
415
+ if ( siteorigin_panels_setting( 'add-widget-class' ) ) {
416
+ $classes[] = 'widget';
417
+ }
418
+ if ( ! empty( $the_widget ) && ! empty( $the_widget->id_base ) ) {
419
+ $classes[] = 'widget_' . $the_widget->id_base;
420
+ }
421
+ if ( ! empty( $the_widget ) && is_array( $the_widget->widget_options ) && ! empty( $the_widget->widget_options['classname'] ) ) {
422
+ $classes[] = $the_widget->widget_options['classname'];
423
+ }
424
+ if ( $is_first ) {
425
+ $classes[] = 'panel-first-child';
426
+ }
427
+ if ( $is_last ) {
428
+ $classes[] = 'panel-last-child';
429
+ }
430
+ $id = 'panel-' . $post_id . '-' . $grid_index . '-' . $cell_index . '-' . $widget_index;
431
+
432
+ // Filter and sanitize the classes
433
+ $classes = apply_filters( 'siteorigin_panels_widget_classes', $classes, $widget_class, $instance, $widget_info );
434
+ $classes = explode( ' ', implode( ' ', $classes ) );
435
+ $classes = array_filter( $classes );
436
+ $classes = array_unique( $classes );
437
+ $classes = array_map( 'sanitize_html_class', $classes );
438
+
439
+ $title_html = siteorigin_panels_setting( 'title-html' );
440
+ if ( strpos( $title_html, '{{title}}' ) !== false ) {
441
+ list( $before_title, $after_title ) = explode( '{{title}}', $title_html, 2 );
442
+ } else {
443
+ $before_title = '<h3 class="widget-title">';
444
+ $after_title = '</h3>';
445
+ }
446
+
447
+ // Attributes of the widget wrapper
448
+ $attributes = apply_filters( 'siteorigin_panels_widget_attributes', array(
449
+ 'id' => $id,
450
+ 'class' => implode( ' ', $classes ),
451
+ 'data-index' => $widget_info['widget_index'],
452
+ ), $widget_info );
453
+
454
+ $before_widget = '<div ';
455
+ foreach ( $attributes as $k => $v ) {
456
+ $before_widget .= esc_attr( $k ) . '="' . esc_attr( $v ) . '" ';
457
+ }
458
+ $before_widget .= '>';
459
+
460
+ $args = array(
461
+ 'before_widget' => $before_widget,
462
+ 'after_widget' => '</div>',
463
+ 'before_title' => $before_title,
464
+ 'after_title' => $after_title,
465
+ 'widget_id' => 'widget-' . $grid_index . '-' . $cell_index . '-' . $widget_index
466
+ );
467
+
468
+ // Let other themes and plugins change the arguments that go to the widget class.
469
+ $args = apply_filters( 'siteorigin_panels_widget_args', $args );
470
+
471
+ // If there is a style wrapper, add it.
472
+ if ( ! empty( $style_wrapper ) ) {
473
+ $args['before_widget'] = $args['before_widget'] . $style_wrapper;
474
+ $args['after_widget'] = '</div>' . $args['after_widget'];
475
+ }
476
+
477
+ // This gives other plugins the chance to take over rendering of widgets
478
+ $widget_html = apply_filters( 'siteorigin_panels_the_widget_html', '', $the_widget, $args, $instance );
479
+
480
+ if ( ! empty( $widget_html ) ) {
481
+ echo $args['before_widget'];
482
+ echo $widget_html;
483
+ echo $args['after_widget'];
484
+ } else if ( ! empty( $the_widget ) && is_a( $the_widget, 'WP_Widget' ) ) {
485
+ $the_widget->widget( $args, $instance );
486
+ } else {
487
+ // This gives themes a chance to display some sort of placeholder for missing widgets
488
+ echo apply_filters( 'siteorigin_panels_missing_widget', $args['before_widget'] . $args['after_widget'], $widget_class, $args, $instance );
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Print inline CSS in the header and footer.
494
+ */
495
+ function print_inline_css() {
496
+ if ( ! empty( $this->inline_css ) ) {
497
+ $the_css = '';
498
+ foreach ( $this->inline_css as $post_id => $css ) {
499
+ if ( empty( $css ) ) {
500
+ continue;
501
+ }
502
+ $the_css .= '/* Layout ' . esc_attr( $post_id ) . ' */ ';
503
+ $the_css .= $css;
504
+ }
505
+
506
+ // Reset the inline CSS
507
+ $this->inline_css = null;
508
+
509
+ switch ( current_filter() ) {
510
+ case 'wp_head' :
511
+ $css_id = 'head';
512
+ break;
513
+
514
+ case 'wp_footer' :
515
+ $css_id = 'footer';
516
+ break;
517
+
518
+ default :
519
+ $css_id = sanitize_html_class( current_filter() );
520
+ break;
521
+ }
522
+
523
+ // Allow third party developers to change the inline styles or remove them completely.
524
+ $the_css = apply_filters( 'siteorigin_panels_inline_styles', $the_css );
525
+
526
+ if ( ! empty( $the_css ) ) {
527
+ ?>
528
+ <style type="text/css" media="all"
529
+ id="siteorigin-panels-layouts-<?php echo esc_attr( $css_id ) ?>"><?php echo $the_css ?></style><?php
530
+ }
531
+ }
532
+ }
533
+
534
+ /**
535
+ * Enqueue the required styles
536
+ */
537
+ function enqueue_styles() {
538
+ // Register the style to support possible lazy loading
539
+ wp_register_style( 'siteorigin-panels-front', SiteOrigin_Panels::front_css_url(), array(), SITEORIGIN_PANELS_VERSION );
540
+ }
541
+
542
+ /**
543
+ * Retrieve panels data for a post or a prebuilt layout or the home page layout.
544
+ *
545
+ * @param string $post_id
546
+ *
547
+ * @return array
548
+ */
549
+ private function get_panels_data_for_post( $post_id ) {
550
+ if ( strpos( $post_id, 'prebuilt:' ) === 0 ) {
551
+ list( $null, $prebuilt_id ) = explode( ':', $post_id, 2 );
552
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
553
+ $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : array();
554
+ } else if ( $post_id == 'home' ) {
555
+ $page_id = get_option( 'page_on_front' );
556
+ if ( empty( $page_id ) ) {
557
+ $page_id = get_option( 'siteorigin_panels_home_page_id' );
558
+ }
559
+
560
+ $panels_data = ! empty( $page_id ) ? get_post_meta( $page_id, 'panels_data', true ) : null;
561
+
562
+ if ( is_null( $panels_data ) ) {
563
+ // Load the default layout
564
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
565
+ $prebuilt_id = siteorigin_panels_setting( 'home-page-default' ) ? siteorigin_panels_setting( 'home-page-default' ) : 'home';
566
+
567
+ $panels_data = ! empty( $layouts[ $prebuilt_id ] ) ? $layouts[ $prebuilt_id ] : current( $layouts );
568
+ }
569
+ } else {
570
+ if ( post_password_required( $post_id ) ) {
571
+ return false;
572
+ }
573
+ $panels_data = get_post_meta( $post_id, 'panels_data', true );
574
+ }
575
+
576
+ return $panels_data;
577
+ }
578
+
579
+ /**
580
+ * Transform flat panels data into a hierarchical structure.
581
+ *
582
+ * @param array $panels_data Flat panels data containing `grids`, `grid_cells`, and `widgets`.
583
+ *
584
+ * @return array Hierarchical structure of rows => cells => widgets.
585
+ */
586
+ public function get_panels_layout_data( $panels_data ) {
587
+ $layout_data = array();
588
+
589
+ foreach ( $panels_data['grids'] as $grid ) {
590
+ $layout_data[] = array(
591
+ 'style' => ! empty( $grid['style'] ) ? $grid['style'] : array(),
592
+ 'ratio' => ! empty( $grid['ratio'] ) ? $grid['ratio'] : '',
593
+ 'ratio_direction' => ! empty( $grid['ratio_direction'] ) ? $grid['ratio_direction'] : '',
594
+ 'color_label' => ! empty( $grid['color_label'] ) ? $grid['color_label'] : '',
595
+ 'label' => ! empty( $grid['label'] ) ? $grid['label'] : '',
596
+ 'cells' => array()
597
+ );
598
+ }
599
+
600
+ foreach ( $panels_data['grid_cells'] as $cell ) {
601
+ $layout_data[ $cell['grid'] ]['cells'][] = array(
602
+ 'widgets' => array(),
603
+ 'style' => ! empty( $cell['style'] ) ? $cell['style'] : array(),
604
+ 'weight' => floatval( $cell['weight'] ),
605
+ );
606
+ }
607
+
608
+ foreach ( $panels_data['widgets'] as $i => $widget ) {
609
+ $widget['panels_info']['widget_index'] = $i;
610
+ $row_index = intval( $widget['panels_info']['grid'] );
611
+ $cell_index = intval( $widget['panels_info']['cell'] );
612
+ $layout_data[ $row_index ]['cells'][ $cell_index ]['widgets'][] = $widget;
613
+ }
614
+
615
+ return $layout_data;
616
+ }
617
+
618
+ /**
619
+ * Outputs the given HTML tag with the given attributes.
620
+ *
621
+ * @param string $tag The HTML element to render.
622
+ * @param array $attributes The attributes for the HTML element.
623
+ *
624
+ */
625
+ private function render_element( $tag, $attributes ) {
626
+
627
+ echo '<' . $tag;
628
+ foreach ( $attributes as $name => $value ) {
629
+ if ( $value ) {
630
+ echo ' ' . $name . '="' . esc_attr( $value ) . '" ';
631
+ }
632
+ }
633
+ echo '>';
634
+
635
+ }
636
+
637
+ /**
638
+ * Render everything for the given row, including:
639
+ * - filters before and after row,
640
+ * - row style wrapper,
641
+ * - row element wrapper with attributes,
642
+ * - child cells
643
+ *
644
+ * @param string $post_id The ID of the post containing this layout.
645
+ * @param int $ri The index of this row.
646
+ * @param array $row The model containing this row's data and child cells.
647
+ * @param array $panels_data A copy of panels_data for filters.
648
+ *
649
+ */
650
+ private function render_row( $post_id, $ri, & $row, & $panels_data ) {
651
+ $row_style_wrapper = $this->start_style_wrapper( 'row', ! empty( $row['style'] ) ? $row['style'] : array(), $post_id . '-' . $ri );
652
+
653
+ $row_classes = array( 'panel-grid' );
654
+ $row_classes[] = ! empty( $row_style_wrapper ) ? 'panel-has-style' : 'panel-no-style';
655
+ $row_classes = apply_filters( 'siteorigin_panels_row_classes', $row_classes, $row );
656
+
657
+ $row_attributes = apply_filters( 'siteorigin_panels_row_attributes', array(
658
+ 'id' => 'pg-' . $post_id . '-' . $ri,
659
+ 'class' => implode( ' ', $row_classes ),
660
+ ), $row );
661
+
662
+ // This allows other themes and plugins to add html before the row
663
+ echo apply_filters( 'siteorigin_panels_before_row', '', $row, $row_attributes );
664
+
665
+ $this->render_element( 'div', $row_attributes );
666
+
667
+ if ( ! empty( $row_style_wrapper ) ) {
668
+ echo $row_style_wrapper;
669
+ }
670
+
671
+ foreach ( $row['cells'] as $ci => & $cell ) {
672
+ $this->render_cell( $post_id, $ri, $ci, $cell, $row['cells'], $panels_data );
673
+ }
674
+
675
+ // Close the style wrapper
676
+ if ( ! empty( $row_style_wrapper ) ) {
677
+ echo '</div>';
678
+ }
679
+
680
+ echo '</div>';
681
+
682
+ // This allows other themes and plugins to add html after the row
683
+ echo apply_filters( 'siteorigin_panels_after_row', '', $row, $row_attributes );
684
+
685
+ }
686
+
687
+ /**
688
+ *
689
+ * Render everything for the given cell, including:
690
+ * - filters before and after cell,
691
+ * - cell element wrapper with attributes,
692
+ * - style wrapper,
693
+ * - child widgets
694
+ *
695
+ * @param string $post_id The ID of the post containing this layout.
696
+ * @param int $ri The index of this cell's parent row.
697
+ * @param int $ci The index of this cell.
698
+ * @param array $cell The model containing this cell's data and child widgets.
699
+ * @param array $cells The array of cells containing this cell.
700
+ * @param array $panels_data A copy of panels_data for filters
701
+ */
702
+ private function render_cell( $post_id, $ri, $ci, & $cell, $cells, & $panels_data ) {
703
+
704
+ $cell_classes = array( 'panel-grid-cell' );
705
+
706
+ if ( empty( $cell['widgets'] ) ) {
707
+ $cell_classes[] = 'panel-grid-cell-empty';
708
+ }
709
+
710
+ if ( $ci == count( $cells ) - 2 && count( $cells[ $ci + 1 ]['widgets'] ) == 0 ) {
711
+ $cell_classes[] = 'panel-grid-cell-mobile-last';
712
+ }
713
+
714
+ // Themes can add their own styles to cells
715
+ $cell_classes = apply_filters( 'siteorigin_panels_cell_classes', $cell_classes, $cell );
716
+
717
+ // Legacy filter, use `siteorigin_panels_cell_classes` instead
718
+ $cell_classes = apply_filters( 'siteorigin_panels_row_cell_classes', $cell_classes, $panels_data, $cell );
719
+
720
+ $cell_attributes = apply_filters( 'siteorigin_panels_cell_attributes', array(
721
+ 'id' => 'pgc-' . $post_id . '-' . $ri . '-' . $ci,
722
+ 'class' => implode( ' ', $cell_classes ),
723
+ ), $cell );
724
+
725
+ // Legacy filter, use `siteorigin_panels_cell_attributes` instead
726
+ $cell_attributes = apply_filters( 'siteorigin_panels_row_cell_attributes', $cell_attributes, $panels_data, $cell );
727
+
728
+ echo apply_filters( 'siteorigin_panels_before_cell', '', $cell, $cell_attributes );
729
+
730
+ $this->render_element( 'div', $cell_attributes );
731
+
732
+ $grid = $panels_data['grids'][ $ri ];
733
+
734
+ if ( empty( $cell['style']['class'] ) && ! empty( $grid['style']['cell_class'] ) ) {
735
+ $cell['style']['class'] = $grid['style']['cell_class'];
736
+ }
737
+
738
+ $cell_style = ! empty( $cell['style'] ) ? $cell['style'] : array();
739
+ $cell_style_wrapper = $this->start_style_wrapper( 'cell', $cell_style, $post_id . '-' . $ri . '-' . $ci );
740
+ if ( ! empty( $cell_style_wrapper ) ) {
741
+ echo $cell_style_wrapper;
742
+ }
743
+
744
+ foreach ( $cell['widgets'] as $wi => & $widget ) {
745
+ $is_last = ( $wi == count( $cell['widgets'] ) - 1 );
746
+ $this->render_widget( $post_id, $ri, $ci, $wi, $widget, $is_last );
747
+ }
748
+
749
+ if ( ! empty( $cell_style_wrapper ) ) {
750
+ echo '</div>';
751
+ }
752
+ echo '</div>';
753
+
754
+ echo apply_filters( 'siteorigin_panels_after_cell', '', $cell, $cell_attributes );
755
+ }
756
+
757
+ /**
758
+ *
759
+ * Gets the style wrapper for this widget and passes it through to `the_widget` along with other required parameters.
760
+ *
761
+ * @param string $post_id The ID of the post containing this layout.
762
+ * @param int $ri The index of this widget's ancestor row.
763
+ * @param int $ci The index of this widget's parent cell.
764
+ * @param int $wi The index of this widget.
765
+ * @param array $widget The model containing this widget's data.
766
+ * @param bool $is_last Whether this is the last widget in the parent cell.
767
+ *
768
+ */
769
+ private function render_widget( $post_id, $ri, $ci, $wi, & $widget, $is_last ) {
770
+
771
+ $widget_style_wrapper = $this->start_style_wrapper(
772
+ 'widget',
773
+ ! empty( $widget['panels_info']['style'] ) ? $widget['panels_info']['style'] : array(),
774
+ $post_id . '-' . $ri . '-' . $ci . '-' . $wi
775
+ );
776
+
777
+ $this->the_widget(
778
+ $widget['panels_info'],
779
+ $widget,
780
+ $ri,
781
+ $ci,
782
+ $wi,
783
+ $wi == 0,
784
+ $is_last,
785
+ $post_id,
786
+ $widget_style_wrapper
787
+ );
788
+
789
+ }
790
+
791
+ public function front_css_url() {
792
+ return siteorigin_panels_url( 'css/front-flex' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' );
793
+ }
794
+ }
inc/settings.php CHANGED
@@ -1,628 +1,628 @@
1
- <?php
2
-
3
- /**
4
- * Class to handle Page Builder settings.
5
- *
6
- * Class SiteOrigin_Panels_Settings
7
- */
8
- class SiteOrigin_Panels_Settings {
9
-
10
- private $settings;
11
- private $fields;
12
- private $settings_saved;
13
-
14
- function __construct() {
15
- $this->settings = array();
16
- $this->fields = array();
17
- $this->settings_saved = false;
18
-
19
- // Admin actions
20
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
21
- add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
22
- add_action( 'after_setup_theme', array( $this, 'clear_cache' ), 100 );
23
-
24
- // Default filters for fields and defaults
25
- add_filter( 'siteorigin_panels_settings_defaults', array( $this, 'settings_defaults' ) );
26
- add_filter( 'siteorigin_panels_default_add_widget_class', array( $this, 'add_widget_class' ) );
27
- add_filter( 'siteorigin_panels_settings_fields', array( $this, 'settings_fields' ) );
28
- }
29
-
30
- /**
31
- * @return SiteOrigin_Panels_Settings
32
- */
33
- static function single() {
34
- static $single;
35
- return empty( $single ) ? $single = new self() : $single;
36
- }
37
-
38
- function clear_cache() {
39
- $this->settings = array();
40
- }
41
-
42
- /**
43
- * Get a settings value
44
- *
45
- * @param string $key
46
- *
47
- * @return array|bool|mixed|null|void
48
- */
49
- function get( $key = '' ) {
50
-
51
- if ( empty( $this->settings ) ) {
52
-
53
- // Get the settings, attempt to fetch new settings first.
54
- $current_settings = get_option( 'siteorigin_panels_settings', false );
55
-
56
- if ( $current_settings === false ) {
57
- // We can't find the settings, so try access old settings
58
- $current_settings = get_option( 'siteorigin_panels_display', array() );
59
- $post_types = get_option( 'siteorigin_panels_post_types' );
60
- if ( ! empty( $post_types ) ) {
61
- $current_settings['post-types'] = $post_types;
62
- }
63
-
64
- // Store the old settings in the new field
65
- update_option( 'siteorigin_panels_settings', $current_settings );
66
- }
67
-
68
- // Get the settings provided by the theme
69
- $theme_settings = get_theme_support( 'siteorigin-panels' );
70
- if ( ! empty( $theme_settings ) ) {
71
- $theme_settings = $theme_settings[0];
72
- } else {
73
- $theme_settings = array();
74
- }
75
-
76
- $this->settings = wp_parse_args( $theme_settings, apply_filters( 'siteorigin_panels_settings_defaults', array() ) );
77
- $this->settings = wp_parse_args( $current_settings, $this->settings );
78
-
79
- // Filter these settings
80
- $this->settings = apply_filters( 'siteorigin_panels_settings', $this->settings );
81
- }
82
-
83
- if ( ! empty( $key ) ) {
84
- return isset( $this->settings[ $key ] ) ? $this->settings[ $key ] : null;
85
- }
86
-
87
- return $this->settings;
88
- }
89
-
90
- /**
91
- * Set a settings value
92
- *
93
- * @param $key
94
- * @param $value
95
- */
96
- function set( $key, $value ) {
97
- $current_settings = get_option( 'siteorigin_panels_settings', array() );
98
- $current_settings[ $key ] = $value;
99
- update_option( 'siteorigin_panels_settings', $current_settings );
100
- }
101
-
102
- /**
103
- * Add default settings for the Page Builder settings.
104
- *
105
- * @param $defaults
106
- *
107
- * @return mixed
108
- */
109
- function settings_defaults( $defaults ) {
110
- $defaults['home-page'] = false;
111
- $defaults['home-page-default'] = false;
112
- $defaults['home-template'] = 'home-panels.php';
113
- $defaults['affiliate-id'] = apply_filters( 'siteorigin_panels_affiliate_id', false );
114
- $defaults['display-teaser'] = true;
115
- $defaults['display-learn'] = true;
116
- $defaults['load-on-attach'] = false;
117
-
118
- // The general fields
119
- $defaults['post-types'] = array( 'page', 'post' );
120
- $defaults['live-editor-quick-link'] = true;
121
- $defaults['admin-widget-count'] = false;
122
- $defaults['parallax-motion'] = '';
123
- $defaults['sidebars-emulator'] = true;
124
-
125
- // Widgets fields
126
- $defaults['title-html'] = '<h3 class="widget-title">{{title}}</h3>';
127
- $defaults['add-widget-class'] = apply_filters( 'siteorigin_panels_default_add_widget_class', true );
128
- $defaults['bundled-widgets'] = get_option( 'siteorigin_panels_is_using_bundled', false );
129
- $defaults['recommended-widgets'] = true;
130
-
131
- // The layout fields
132
- $defaults['responsive'] = true;
133
- $defaults['tablet-layout'] = false;
134
- $defaults['legacy-layout'] = 'auto';
135
- $defaults['tablet-width'] = 1024;
136
- $defaults['mobile-width'] = 780;
137
- $defaults['margin-bottom'] = 30;
138
- $defaults['margin-bottom-last-row'] = false;
139
- $defaults['margin-sides'] = 30;
140
- $defaults['full-width-container'] = 'body';
141
-
142
- // Content fields
143
- $defaults['copy-content'] = true;
144
- $defaults['copy-styles'] = false;
145
-
146
- return $defaults;
147
- }
148
-
149
- /**
150
- * Set the option on whether to add widget classes for known themes
151
- *
152
- * @param $add_class
153
- *
154
- * @return bool
155
- */
156
- function add_widget_class( $add_class ) {
157
-
158
- switch ( get_option( 'stylesheet' ) ) {
159
- case 'twentysixteen';
160
- $add_class = false;
161
- break;
162
- }
163
-
164
-
165
- return $add_class;
166
- }
167
-
168
- /**
169
- * Enqueue admin scripts
170
- *
171
- * @param $prefix
172
- */
173
- function admin_scripts( $prefix ) {
174
- if ( $prefix != 'settings_page_siteorigin_panels' ) {
175
- return;
176
- }
177
- wp_enqueue_style(
178
- 'siteorigin-panels-settings',
179
- siteorigin_panels_url( 'settings/admin-settings.css' ),
180
- array(),
181
- SITEORIGIN_PANELS_VERSION
182
- );
183
- wp_enqueue_script(
184
- 'siteorigin-panels-settings',
185
- siteorigin_panels_url( 'settings/admin-settings' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
186
- array(),
187
- SITEORIGIN_PANELS_VERSION
188
- );
189
- }
190
-
191
- /**
192
- * Add the Page Builder settings page
193
- */
194
- function add_settings_page() {
195
- $page = add_options_page( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ), __( 'Page Builder', 'siteorigin-panels' ), 'manage_options', 'siteorigin_panels', array(
196
- $this,
197
- 'display_settings_page'
198
- ) );
199
- add_action( 'load-' . $page, array( $this, 'add_help_tab' ) );
200
- add_action( 'load-' . $page, array( $this, 'save_settings' ) );
201
- }
202
-
203
- /**
204
- * Display the Page Builder settings page
205
- */
206
- function display_settings_page() {
207
- $settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
208
- include plugin_dir_path( __FILE__ ) . '../settings/tpl/settings.php';
209
- }
210
-
211
- /**
212
- * Add a settings help tab
213
- */
214
- function add_help_tab() {
215
- $screen = get_current_screen();
216
- ob_start();
217
- include plugin_dir_path( __FILE__ ) . '../settings/tpl/help.php';
218
- $content = ob_get_clean();
219
-
220
- $screen->add_help_tab( array(
221
- 'id' => 'panels-help-tab',
222
- 'title' => __( 'Page Builder Settings', 'siteorigin-panels' ),
223
- 'content' => $content
224
- ) );
225
- }
226
-
227
- /**
228
- * Add the default Page Builder settings.
229
- *
230
- * @param $fields
231
- *
232
- * @return mixed
233
- */
234
- function settings_fields( $fields ) {
235
- // The post types fields
236
-
237
- $fields['general'] = array(
238
- 'title' => __( 'General', 'siteorigin-panels' ),
239
- 'fields' => array(),
240
- );
241
-
242
- $fields['general']['fields']['post-types'] = array(
243
- 'type' => 'select_multi',
244
- 'label' => __( 'Post Types', 'siteorigin-panels' ),
245
- 'options' => $this->get_post_types(),
246
- 'description' => __( 'The post types to use Page Builder on.', 'siteorigin-panels' ),
247
- );
248
-
249
- $fields['general']['fields']['live-editor-quick-link'] = array(
250
- 'type' => 'checkbox',
251
- 'label' => __( 'Live Editor Quick Link', 'siteorigin-panels' ),
252
- 'description' => __( 'Display a Live Editor button in the admin bar.', 'siteorigin-panels' ),
253
- );
254
-
255
- $fields['general']['fields']['admin-widget-count'] = array(
256
- 'type' => 'checkbox',
257
- 'label' => __( 'Display Widget Count', 'siteorigin-panels' ),
258
- 'description' => __( "Display a widget count in the admin lists of posts/pages where you're using Page Builder.", 'siteorigin-panels' ),
259
- );
260
-
261
- $fields['general']['fields']['parallax-motion'] = array(
262
- 'type' => 'float',
263
- 'label' => __( 'Limit Parallax Motion', 'siteorigin-panels' ),
264
- 'description' => __( 'How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect.', 'siteorigin-panels' ),
265
- );
266
-
267
- $fields['general']['fields']['sidebars-emulator'] = array(
268
- 'type' => 'checkbox',
269
- 'label' => __( 'Sidebars Emulator', 'siteorigin-panels' ),
270
- 'description' => __( 'Page Builder will create an emulated sidebar, that contains all widgets in the page.', 'siteorigin-panels' ),
271
- );
272
-
273
- $fields['general']['fields']['display-teaser'] = array(
274
- 'type' => 'checkbox',
275
- 'label' => __('Upgrade Teaser', 'siteorigin-panels'),
276
- 'description' => sprintf(
277
- __('Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar.', 'siteorigin-panels'),
278
- '<a href="siteorigin.com/downloads/premium/" target="_blank" rel="noopener noreferrer">',
279
- '</a>'
280
- )
281
- );
282
-
283
- $fields['general']['fields']['display-learn'] = array(
284
- 'type' => 'checkbox',
285
- 'label' => __( 'Page Builder Learning', 'siteorigin-panels' ),
286
- 'description' => __( 'Display buttons for Page Builder learning.', 'siteorigin-panels' )
287
- );
288
-
289
- $fields['general']['fields']['load-on-attach'] = array(
290
- 'type' => 'checkbox',
291
- 'label' => __( 'Default To Page Builder Interface', 'siteorigin-panels' ),
292
- 'description' => __( 'New posts/pages that you create will start with the Page Builder loaded.', 'siteorigin-panels' )
293
- );
294
-
295
- // The widgets fields
296
-
297
- $fields['widgets'] = array(
298
- 'title' => __( 'Widgets', 'siteorigin-panels' ),
299
- 'fields' => array(),
300
- );
301
-
302
- $fields['widgets']['fields']['title-html'] = array(
303
- 'type' => 'html',
304
- 'label' => __( 'Widget Title HTML', 'siteorigin-panels' ),
305
- 'description' => __( 'The HTML used for widget titles. {{title}} is replaced with the widget title.', 'siteorigin-panels' ),
306
- );
307
-
308
- $fields['widgets']['fields']['add-widget-class'] = array(
309
- 'type' => 'checkbox',
310
- 'label' => __( 'Add Widget Class', 'siteorigin-panels' ),
311
- 'description' => __( "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts.", 'siteorigin-panels' ),
312
- );
313
-
314
- $fields['widgets']['fields']['bundled-widgets'] = array(
315
- 'type' => 'checkbox',
316
- 'label' => __( 'Legacy Bundled Widgets', 'siteorigin-panels' ),
317
- 'description' => __( 'Load legacy widgets from Page Builder 1.', 'siteorigin-panels' ),
318
- );
319
-
320
- $fields['widgets']['fields']['recommended-widgets'] = array(
321
- 'type' => 'checkbox',
322
- 'label' => __( 'Recommended Widgets', 'siteorigin-panels' ),
323
- 'description' => __( 'Display recommend widgets in Page Builder add widget dialog.', 'siteorigin-panels' ),
324
- );
325
-
326
- // The layout fields
327
-
328
- $fields['layout'] = array(
329
- 'title' => __( 'Layout', 'siteorigin-panels' ),
330
- 'fields' => array(),
331
- );
332
-
333
- // The layout fields
334
-
335
- $fields['layout']['fields']['responsive'] = array(
336
- 'type' => 'checkbox',
337
- 'label' => __( 'Responsive Layout', 'siteorigin-panels' ),
338
- 'description' => __( 'Collapse widgets, rows and columns on mobile devices.', 'siteorigin-panels' ),
339
- );
340
-
341
- $fields['layout']['fields']['tablet-layout'] = array(
342
- 'type' => 'checkbox',
343
- 'label' => __( 'Use Tablet Layout', 'siteorigin-panels' ),
344
- 'description' => __( 'Collapses columns differently on tablet devices.', 'siteorigin-panels' ),
345
- );
346
-
347
- $fields['layout']['fields']['legacy-layout'] = array(
348
- 'type' => 'select',
349
- 'options' => array(
350
- 'auto' => __( 'Detect older browsers', 'siteorigin-panels' ),
351
- 'never' => __( 'Never', 'siteorigin-panels' ),
352
- 'always' => __( 'Always', 'siteorigin-panels' ),
353
- ),
354
- 'label' => __( 'Use Legacy Layout Engine', 'siteorigin-panels' ),
355
- 'description' => __( 'The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers.', 'siteorigin-panels' ),
356
- );
357
-
358
- $fields['layout']['fields']['tablet-width'] = array(
359
- 'type' => 'number',
360
- 'unit' => 'px',
361
- 'label' => __( 'Tablet Width', 'siteorigin-panels' ),
362
- 'description' => __( 'Device width, in pixels, to collapse into a tablet view .', 'siteorigin-panels' ),
363
- );
364
-
365
- $fields['layout']['fields']['mobile-width'] = array(
366
- 'type' => 'number',
367
- 'unit' => 'px',
368
- 'label' => __( 'Mobile Width', 'siteorigin-panels' ),
369
- 'description' => __( 'Device width, in pixels, to collapse into a mobile view .', 'siteorigin-panels' ),
370
- );
371
-
372
- $fields['layout']['fields']['margin-bottom'] = array(
373
- 'type' => 'number',
374
- 'unit' => 'px',
375
- 'label' => __( 'Row/Widget Bottom Margin', 'siteorigin-panels' ),
376
- 'description' => __( 'Default margin below rows and widgets.', 'siteorigin-panels' ),
377
- );
378
-
379
- $fields['layout']['fields']['margin-bottom-last-row'] = array(
380
- 'type' => 'checkbox',
381
- 'label' => __( 'Last Row With Margin', 'siteorigin-panels' ),
382
- 'description' => __( 'Allow margin in last row.', 'siteorigin-panels' ),
383
- );
384
-
385
- $fields['layout']['fields']['margin-sides'] = array(
386
- 'type' => 'number',
387
- 'unit' => 'px',
388
- 'label' => __( 'Row Gutter', 'siteorigin-panels' ),
389
- 'description' => __( 'Default spacing between columns in each row.', 'siteorigin-panels' ),
390
- 'keywords' => 'margin',
391
- );
392
-
393
- $fields['layout']['fields']['full-width-container'] = array(
394
- 'type' => 'text',
395
- 'label' => __( 'Full Width Container', 'siteorigin-panels' ),
396
- 'description' => __( 'The container used for the full width layout.', 'siteorigin-panels' ),
397
- 'keywords' => 'full width, container, stretch',
398
- );
399
-
400
- // The content fields
401
-
402
- $fields['content'] = array(
403
- 'title' => __( 'Content', 'siteorigin-panels' ),
404
- 'fields' => array(),
405
- );
406
-
407
- $fields['content']['fields']['copy-content'] = array(
408
- 'type' => 'checkbox',
409
- 'label' => __( 'Copy Content', 'siteorigin-panels' ),
410
- 'description' => __( 'Copy content from Page Builder to post content.', 'siteorigin-panels' ),
411
- );
412
-
413
- $fields['content']['fields']['copy-styles'] = array(
414
- 'type' => 'checkbox',
415
- 'label' => __( 'Copy Styles', 'siteorigin-panels' ),
416
- 'description' => __( 'Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated.', 'siteorigin-panels' ),
417
- );
418
-
419
- return $fields;
420
- }
421
-
422
- /**
423
- * Display a settings field
424
- *
425
- * @param $field_id
426
- * @param $field
427
- */
428
- function display_field( $field_id, $field ) {
429
- $value = siteorigin_panels_setting( $field_id );
430
-
431
- $field_name = 'panels_setting[' . $field_id . ']';
432
-
433
- switch ( $field['type'] ) {
434
- case 'text':
435
- case 'float':
436
- ?><input name="<?php echo esc_attr( $field_name ) ?>"
437
- class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>" type="text"
438
- value="<?php echo esc_attr( $value ) ?>" /> <?php
439
- break;
440
-
441
- case 'number':
442
- ?>
443
- <input name="<?php echo esc_attr( $field_name ) ?>" type="number"
444
- class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>"
445
- value="<?php echo esc_attr( $value ) ?>"/>
446
- <?php
447
- if ( ! empty( $field['unit'] ) ) {
448
- echo esc_html( $field['unit'] );
449
- }
450
- break;
451
-
452
- case 'html':
453
- ?><textarea name="<?php echo esc_attr( $field_name ) ?>"
454
- class="panels-setting-<?php echo esc_attr( $field['type'] ) ?> widefat"
455
- rows="<?php echo ! empty( $field['rows'] ) ? intval( $field['rows'] ) : 2 ?>"><?php echo esc_textarea( $value ) ?></textarea> <?php
456
- break;
457
-
458
- case 'checkbox':
459
- ?>
460
- <label class="widefat">
461
- <input name="<?php echo esc_attr( $field_name ) ?>"
462
- type="checkbox" <?php checked( ! empty( $value ) ) ?> />
463
- <?php echo ! empty( $field['checkbox_text'] ) ? esc_html( $field['checkbox_text'] ) : __( 'Enabled', 'siteorigin-panels' ) ?>
464
- </label>
465
- <?php
466
- break;
467
-
468
- case 'select':
469
- ?>
470
- <select name="<?php echo esc_attr( $field_name ) ?>">
471
- <?php foreach ( $field['options'] as $option_id => $option ) : ?>
472
- <option
473
- value="<?php echo esc_attr( $option_id ) ?>" <?php selected( $option_id, $value ) ?>><?php echo esc_html( $option ) ?></option>
474
- <?php endforeach; ?>
475
- </select>
476
- <?php
477
- break;
478
-
479
- case 'select_multi':
480
- foreach ( $field['options'] as $option_id => $option ) {
481
- ?>
482
- <label class="widefat">
483
- <input name="<?php echo esc_attr( $field_name ) ?>[<?php echo esc_attr( $option_id ) ?>]"
484
- type="checkbox" <?php checked( in_array( $option_id, $value ) ) ?> />
485
- <?php echo esc_html( $option ) ?>
486
- </label>
487
- <?php
488
- }
489
-
490
- break;
491
- }
492
- }
493
-
494
- /**
495
- * Save the Page Builder settings.
496
- */
497
- function save_settings() {
498
- $screen = get_current_screen();
499
- if ( $screen->base != 'settings_page_siteorigin_panels' ) {
500
- return;
501
- }
502
-
503
- if ( ! current_user_can( 'manage_options' ) ) {
504
- return;
505
- }
506
- if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'panels-settings' ) ) {
507
- return;
508
- }
509
- if ( empty( $_POST['panels_setting'] ) ) {
510
- return;
511
- }
512
-
513
- $values = array();
514
- $post = stripslashes_deep( $_POST['panels_setting'] );
515
- $settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
516
-
517
- if ( empty( $settings_fields ) ) {
518
- return;
519
- }
520
-
521
- foreach ( $settings_fields as $section_id => $section ) {
522
- if ( empty( $section['fields'] ) ) {
523
- continue;
524
- }
525
-
526
- foreach ( $section['fields'] as $field_id => $field ) {
527
- // Sanitize the fields
528
- switch ( $field['type'] ) {
529
- case 'text' :
530
- $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? sanitize_text_field( $post[ $field_id ] ) : '';
531
- break;
532
-
533
- case 'number':
534
- if ( $post[ $field_id ] != '' ) {
535
- $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? intval( $post[ $field_id ] ) : 0;
536
- } else {
537
- $values[ $field_id ] = '';
538
- }
539
- break;
540
-
541
- case 'float':
542
- if ( $post[ $field_id ] != '' ) {
543
- $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? floatval( $post[ $field_id ] ) : 0;
544
- } else {
545
- $values[ $field_id ] = '';
546
- }
547
- break;
548
-
549
- case 'html':
550
- $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
551
- $values[ $field_id ] = wp_kses_post( $values[ $field_id ] );
552
- $values[ $field_id ] = force_balance_tags( $values[ $field_id ] );
553
- break;
554
-
555
- case 'checkbox':
556
- $values[ $field_id ] = ! empty( $post[ $field_id ] );
557
- break;
558
-
559
- case 'select':
560
- $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
561
- if ( ! in_array( $values[ $field_id ], array_keys( $field['options'] ) ) ) {
562
- unset( $values[ $field_id ] );
563
- }
564
- break;
565
-
566
- case 'select_multi':
567
- $values[ $field_id ] = array();
568
- $multi_values = array();
569
- foreach ( $field['options'] as $option_id => $option ) {
570
- $multi_values[ $option_id ] = ! empty( $post[ $field_id ][ $option_id ] );
571
- }
572
- foreach ( $multi_values as $k => $v ) {
573
- if ( $v ) {
574
- $values[ $field_id ][] = $k;
575
- }
576
- }
577
-
578
- break;
579
- }
580
- }
581
- }
582
-
583
- // Don't let mobile width go below 320
584
- $values[ 'mobile-width' ] = max( $values[ 'mobile-width' ], 320 );
585
-
586
- // Save the values to the database
587
- update_option( 'siteorigin_panels_settings', $values );
588
- do_action( 'siteorigin_panels_save_settings', $values );
589
- $this->settings = wp_parse_args( $values, $this->settings );
590
- $this->settings_saved = true;
591
- }
592
-
593
- /**
594
- * Get a post type array
595
- *
596
- * @return array
597
- */
598
- function get_post_types() {
599
- $post_types = get_post_types( array( '_builtin' => false ) );
600
-
601
- $types = array(
602
- 'page' => 'page',
603
- 'post' => 'post'
604
- );
605
-
606
- // Don't use `array_merge` here as it will break things if a post type has a numeric slug.
607
- foreach ( $post_types as $key => $value ) {
608
- $types[ $key ] = $value;
609
- }
610
-
611
- // These are post types we know we don't want to show Page Builder on
612
- unset( $types['ml-slider'] );
613
-
614
- foreach ( $types as $type_id => $type ) {
615
- $type_object = get_post_type_object( $type_id );
616
-
617
- if ( ! $type_object->show_ui ) {
618
- unset( $types[ $type_id ] );
619
- continue;
620
- }
621
-
622
- $types[ $type_id ] = $type_object->label;
623
- }
624
-
625
- return apply_filters( 'siteorigin_panels_settings_enabled_post_types', $types );
626
- }
627
-
628
- }
1
+ <?php
2
+
3
+ /**
4
+ * Class to handle Page Builder settings.
5
+ *
6
+ * Class SiteOrigin_Panels_Settings
7
+ */
8
+ class SiteOrigin_Panels_Settings {
9
+
10
+ private $settings;
11
+ private $fields;
12
+ private $settings_saved;
13
+
14
+ function __construct() {
15
+ $this->settings = array();
16
+ $this->fields = array();
17
+ $this->settings_saved = false;
18
+
19
+ // Admin actions
20
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
21
+ add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
22
+ add_action( 'after_setup_theme', array( $this, 'clear_cache' ), 100 );
23
+
24
+ // Default filters for fields and defaults
25
+ add_filter( 'siteorigin_panels_settings_defaults', array( $this, 'settings_defaults' ) );
26
+ add_filter( 'siteorigin_panels_default_add_widget_class', array( $this, 'add_widget_class' ) );
27
+ add_filter( 'siteorigin_panels_settings_fields', array( $this, 'settings_fields' ) );
28
+ }
29
+
30
+ /**
31
+ * @return SiteOrigin_Panels_Settings
32
+ */
33
+ static function single() {
34
+ static $single;
35
+ return empty( $single ) ? $single = new self() : $single;
36
+ }
37
+
38
+ function clear_cache() {
39
+ $this->settings = array();
40
+ }
41
+
42
+ /**
43
+ * Get a settings value
44
+ *
45
+ * @param string $key
46
+ *
47
+ * @return array|bool|mixed|null|void
48
+ */
49
+ function get( $key = '' ) {
50
+
51
+ if ( empty( $this->settings ) ) {
52
+
53
+ // Get the settings, attempt to fetch new settings first.
54
+ $current_settings = get_option( 'siteorigin_panels_settings', false );
55
+
56
+ if ( $current_settings === false ) {
57
+ // We can't find the settings, so try access old settings
58
+ $current_settings = get_option( 'siteorigin_panels_display', array() );
59
+ $post_types = get_option( 'siteorigin_panels_post_types' );
60
+ if ( ! empty( $post_types ) ) {
61
+ $current_settings['post-types'] = $post_types;
62
+ }
63
+
64
+ // Store the old settings in the new field
65
+ update_option( 'siteorigin_panels_settings', $current_settings );
66
+ }
67
+
68
+ // Get the settings provided by the theme
69
+ $theme_settings = get_theme_support( 'siteorigin-panels' );
70
+ if ( ! empty( $theme_settings ) ) {
71
+ $theme_settings = $theme_settings[0];
72
+ } else {
73
+ $theme_settings = array();
74
+ }
75
+
76
+ $this->settings = wp_parse_args( $theme_settings, apply_filters( 'siteorigin_panels_settings_defaults', array() ) );
77
+ $this->settings = wp_parse_args( $current_settings, $this->settings );
78
+
79
+ // Filter these settings
80
+ $this->settings = apply_filters( 'siteorigin_panels_settings', $this->settings );
81
+ }
82
+
83
+ if ( ! empty( $key ) ) {
84
+ return isset( $this->settings[ $key ] ) ? $this->settings[ $key ] : null;
85
+ }
86
+
87
+ return $this->settings;
88
+ }
89
+
90
+ /**
91
+ * Set a settings value
92
+ *
93
+ * @param $key
94
+ * @param $value
95
+ */
96
+ function set( $key, $value ) {
97
+ $current_settings = get_option( 'siteorigin_panels_settings', array() );
98
+ $current_settings[ $key ] = $value;
99
+ update_option( 'siteorigin_panels_settings', $current_settings );
100
+ }
101
+
102
+ /**
103
+ * Add default settings for the Page Builder settings.
104
+ *
105
+ * @param $defaults
106
+ *
107
+ * @return mixed
108
+ */
109
+ function settings_defaults( $defaults ) {
110
+ $defaults['home-page'] = false;
111
+ $defaults['home-page-default'] = false;
112
+ $defaults['home-template'] = 'home-panels.php';
113
+ $defaults['affiliate-id'] = apply_filters( 'siteorigin_panels_affiliate_id', false );
114
+ $defaults['display-teaser'] = true;
115
+ $defaults['display-learn'] = true;
116
+ $defaults['load-on-attach'] = false;
117
+
118
+ // The general fields
119
+ $defaults['post-types'] = array( 'page', 'post' );
120
+ $defaults['live-editor-quick-link'] = true;
121
+ $defaults['admin-widget-count'] = false;
122
+ $defaults['parallax-motion'] = '';
123
+ $defaults['sidebars-emulator'] = true;
124
+
125
+ // Widgets fields
126
+ $defaults['title-html'] = '<h3 class="widget-title">{{title}}</h3>';
127
+ $defaults['add-widget-class'] = apply_filters( 'siteorigin_panels_default_add_widget_class', true );
128
+ $defaults['bundled-widgets'] = get_option( 'siteorigin_panels_is_using_bundled', false );
129
+ $defaults['recommended-widgets'] = true;
130
+
131
+ // The layout fields
132
+ $defaults['responsive'] = true;
133
+ $defaults['tablet-layout'] = false;
134
+ $defaults['legacy-layout'] = 'auto';
135
+ $defaults['tablet-width'] = 1024;
136
+ $defaults['mobile-width'] = 780;
137
+ $defaults['margin-bottom'] = 30;
138
+ $defaults['margin-bottom-last-row'] = false;
139
+ $defaults['margin-sides'] = 30;
140
+ $defaults['full-width-container'] = 'body';
141
+
142
+ // Content fields
143
+ $defaults['copy-content'] = true;
144
+ $defaults['copy-styles'] = false;
145
+
146
+ return $defaults;
147
+ }
148
+
149
+ /**
150
+ * Set the option on whether to add widget classes for known themes
151
+ *
152
+ * @param $add_class
153
+ *
154
+ * @return bool
155
+ */
156
+ function add_widget_class( $add_class ) {
157
+
158
+ switch ( get_option( 'stylesheet' ) ) {
159
+ case 'twentysixteen';
160
+ $add_class = false;
161
+ break;
162
+ }
163
+
164
+
165
+ return $add_class;
166
+ }
167
+
168
+ /**
169
+ * Enqueue admin scripts
170
+ *
171
+ * @param $prefix
172
+ */
173
+ function admin_scripts( $prefix ) {
174
+ if ( $prefix != 'settings_page_siteorigin_panels' ) {
175
+ return;
176
+ }
177
+ wp_enqueue_style(
178
+ 'siteorigin-panels-settings',
179
+ siteorigin_panels_url( 'settings/admin-settings.css' ),
180
+ array(),
181
+ SITEORIGIN_PANELS_VERSION
182
+ );
183
+ wp_enqueue_script(
184
+ 'siteorigin-panels-settings',
185
+ siteorigin_panels_url( 'settings/admin-settings' . SITEORIGIN_PANELS_JS_SUFFIX . '.js' ),
186
+ array(),
187
+ SITEORIGIN_PANELS_VERSION
188
+ );
189
+ }
190
+
191
+ /**
192
+ * Add the Page Builder settings page
193
+ */
194
+ function add_settings_page() {
195
+ $page = add_options_page( __( 'SiteOrigin Page Builder', 'siteorigin-panels' ), __( 'Page Builder', 'siteorigin-panels' ), 'manage_options', 'siteorigin_panels', array(
196
+ $this,
197
+ 'display_settings_page'
198
+ ) );
199
+ add_action( 'load-' . $page, array( $this, 'add_help_tab' ) );
200
+ add_action( 'load-' . $page, array( $this, 'save_settings' ) );
201
+ }
202
+
203
+ /**
204
+ * Display the Page Builder settings page
205
+ */
206
+ function display_settings_page() {
207
+ $settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
208
+ include plugin_dir_path( __FILE__ ) . '../settings/tpl/settings.php';
209
+ }
210
+
211
+ /**
212
+ * Add a settings help tab
213
+ */
214
+ function add_help_tab() {
215
+ $screen = get_current_screen();
216
+ ob_start();
217
+ include plugin_dir_path( __FILE__ ) . '../settings/tpl/help.php';
218
+ $content = ob_get_clean();
219
+
220
+ $screen->add_help_tab( array(
221
+ 'id' => 'panels-help-tab',
222
+ 'title' => __( 'Page Builder Settings', 'siteorigin-panels' ),
223
+ 'content' => $content
224
+ ) );
225
+ }
226
+
227
+ /**
228
+ * Add the default Page Builder settings.
229
+ *
230
+ * @param $fields
231
+ *
232
+ * @return mixed
233
+ */
234
+ function settings_fields( $fields ) {
235
+ // The post types fields
236
+
237
+ $fields['general'] = array(
238
+ 'title' => __( 'General', 'siteorigin-panels' ),
239
+ 'fields' => array(),
240
+ );
241
+
242
+ $fields['general']['fields']['post-types'] = array(
243
+ 'type' => 'select_multi',
244
+ 'label' => __( 'Post Types', 'siteorigin-panels' ),
245
+ 'options' => $this->get_post_types(),
246
+ 'description' => __( 'The post types to use Page Builder on.', 'siteorigin-panels' ),
247
+ );
248
+
249
+ $fields['general']['fields']['live-editor-quick-link'] = array(
250
+ 'type' => 'checkbox',
251
+ 'label' => __( 'Live Editor Quick Link', 'siteorigin-panels' ),
252
+ 'description' => __( 'Display a Live Editor button in the admin bar.', 'siteorigin-panels' ),
253
+ );
254
+
255
+ $fields['general']['fields']['admin-widget-count'] = array(
256
+ 'type' => 'checkbox',
257
+ 'label' => __( 'Display Widget Count', 'siteorigin-panels' ),
258
+ 'description' => __( "Display a widget count in the admin lists of posts/pages where you're using Page Builder.", 'siteorigin-panels' ),
259
+ );
260
+
261
+ $fields['general']['fields']['parallax-motion'] = array(
262
+ 'type' => 'float',
263
+ 'label' => __( 'Limit Parallax Motion', 'siteorigin-panels' ),
264
+ 'description' => __( 'How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect.', 'siteorigin-panels' ),
265
+ );
266
+
267
+ $fields['general']['fields']['sidebars-emulator'] = array(
268
+ 'type' => 'checkbox',
269
+ 'label' => __( 'Sidebars Emulator', 'siteorigin-panels' ),
270
+ 'description' => __( 'Page Builder will create an emulated sidebar, that contains all widgets in the page.', 'siteorigin-panels' ),
271
+ );
272
+
273
+ $fields['general']['fields']['display-teaser'] = array(
274
+ 'type' => 'checkbox',
275
+ 'label' => __('Upgrade Teaser', 'siteorigin-panels'),
276
+ 'description' => sprintf(
277
+ __('Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar.', 'siteorigin-panels'),
278
+ '<a href="siteorigin.com/downloads/premium/" target="_blank" rel="noopener noreferrer">',
279
+ '</a>'
280
+ )
281
+ );
282
+
283
+ $fields['general']['fields']['display-learn'] = array(
284
+ 'type' => 'checkbox',
285
+ 'label' => __( 'Page Builder Learning', 'siteorigin-panels' ),
286
+ 'description' => __( 'Display buttons for Page Builder learning.', 'siteorigin-panels' )
287
+ );
288
+
289
+ $fields['general']['fields']['load-on-attach'] = array(
290
+ 'type' => 'checkbox',
291
+ 'label' => __( 'Default To Page Builder Interface', 'siteorigin-panels' ),
292
+ 'description' => __( 'New posts/pages that you create will start with the Page Builder loaded.', 'siteorigin-panels' )
293
+ );
294
+
295
+ // The widgets fields
296
+
297
+ $fields['widgets'] = array(
298
+ 'title' => __( 'Widgets', 'siteorigin-panels' ),
299
+ 'fields' => array(),
300
+ );
301
+
302
+ $fields['widgets']['fields']['title-html'] = array(
303
+ 'type' => 'html',
304
+ 'label' => __( 'Widget Title HTML', 'siteorigin-panels' ),
305
+ 'description' => __( 'The HTML used for widget titles. {{title}} is replaced with the widget title.', 'siteorigin-panels' ),
306
+ );
307
+
308
+ $fields['widgets']['fields']['add-widget-class'] = array(
309
+ 'type' => 'checkbox',
310
+ 'label' => __( 'Add Widget Class', 'siteorigin-panels' ),
311
+ 'description' => __( "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts.", 'siteorigin-panels' ),
312
+ );
313
+
314
+ $fields['widgets']['fields']['bundled-widgets'] = array(
315
+ 'type' => 'checkbox',
316
+ 'label' => __( 'Legacy Bundled Widgets', 'siteorigin-panels' ),
317
+ 'description' => __( 'Load legacy widgets from Page Builder 1.', 'siteorigin-panels' ),
318
+ );
319
+
320
+ $fields['widgets']['fields']['recommended-widgets'] = array(
321
+ 'type' => 'checkbox',
322
+ 'label' => __( 'Recommended Widgets', 'siteorigin-panels' ),
323
+ 'description' => __( 'Display recommend widgets in Page Builder add widget dialog.', 'siteorigin-panels' ),
324
+ );
325
+
326
+ // The layout fields
327
+
328
+ $fields['layout'] = array(
329
+ 'title' => __( 'Layout', 'siteorigin-panels' ),
330
+ 'fields' => array(),
331
+ );
332
+
333
+ // The layout fields
334
+
335
+ $fields['layout']['fields']['responsive'] = array(
336
+ 'type' => 'checkbox',
337
+ 'label' => __( 'Responsive Layout', 'siteorigin-panels' ),
338
+ 'description' => __( 'Collapse widgets, rows and columns on mobile devices.', 'siteorigin-panels' ),
339
+ );
340
+
341
+ $fields['layout']['fields']['tablet-layout'] = array(
342
+ 'type' => 'checkbox',
343
+ 'label' => __( 'Use Tablet Layout', 'siteorigin-panels' ),
344
+ 'description' => __( 'Collapses columns differently on tablet devices.', 'siteorigin-panels' ),
345
+ );
346
+
347
+ $fields['layout']['fields']['legacy-layout'] = array(
348
+ 'type' => 'select',
349
+ 'options' => array(
350
+ 'auto' => __( 'Detect older browsers', 'siteorigin-panels' ),
351
+ 'never' => __( 'Never', 'siteorigin-panels' ),
352
+ 'always' => __( 'Always', 'siteorigin-panels' ),
353
+ ),
354
+ 'label' => __( 'Use Legacy Layout Engine', 'siteorigin-panels' ),
355
+ 'description' => __( 'The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers.', 'siteorigin-panels' ),
356
+ );
357
+
358
+ $fields['layout']['fields']['tablet-width'] = array(
359
+ 'type' => 'number',
360
+ 'unit' => 'px',
361
+ 'label' => __( 'Tablet Width', 'siteorigin-panels' ),
362
+ 'description' => __( 'Device width, in pixels, to collapse into a tablet view .', 'siteorigin-panels' ),
363
+ );
364
+
365
+ $fields['layout']['fields']['mobile-width'] = array(
366
+ 'type' => 'number',
367
+ 'unit' => 'px',
368
+ 'label' => __( 'Mobile Width', 'siteorigin-panels' ),
369
+ 'description' => __( 'Device width, in pixels, to collapse into a mobile view .', 'siteorigin-panels' ),
370
+ );
371
+
372
+ $fields['layout']['fields']['margin-bottom'] = array(
373
+ 'type' => 'number',
374
+ 'unit' => 'px',
375
+ 'label' => __( 'Row/Widget Bottom Margin', 'siteorigin-panels' ),
376
+ 'description' => __( 'Default margin below rows and widgets.', 'siteorigin-panels' ),
377
+ );
378
+
379
+ $fields['layout']['fields']['margin-bottom-last-row'] = array(
380
+ 'type' => 'checkbox',
381
+ 'label' => __( 'Last Row With Margin', 'siteorigin-panels' ),
382
+ 'description' => __( 'Allow margin in last row.', 'siteorigin-panels' ),
383
+ );
384
+
385
+ $fields['layout']['fields']['margin-sides'] = array(
386
+ 'type' => 'number',
387
+ 'unit' => 'px',
388
+ 'label' => __( 'Row Gutter', 'siteorigin-panels' ),
389
+ 'description' => __( 'Default spacing between columns in each row.', 'siteorigin-panels' ),
390
+ 'keywords' => 'margin',
391
+ );
392
+
393
+ $fields['layout']['fields']['full-width-container'] = array(
394
+ 'type' => 'text',
395
+ 'label' => __( 'Full Width Container', 'siteorigin-panels' ),
396
+ 'description' => __( 'The container used for the full width layout.', 'siteorigin-panels' ),
397
+ 'keywords' => 'full width, container, stretch',
398
+ );
399
+
400
+ // The content fields
401
+
402
+ $fields['content'] = array(
403
+ 'title' => __( 'Content', 'siteorigin-panels' ),
404
+ 'fields' => array(),
405
+ );
406
+
407
+ $fields['content']['fields']['copy-content'] = array(
408
+ 'type' => 'checkbox',
409
+ 'label' => __( 'Copy Content', 'siteorigin-panels' ),
410
+ 'description' => __( 'Copy content from Page Builder to post content.', 'siteorigin-panels' ),
411
+ );
412
+
413
+ $fields['content']['fields']['copy-styles'] = array(
414
+ 'type' => 'checkbox',
415
+ 'label' => __( 'Copy Styles', 'siteorigin-panels' ),
416
+ 'description' => __( 'Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated.', 'siteorigin-panels' ),
417
+ );
418
+
419
+ return $fields;
420
+ }
421
+
422
+ /**
423
+ * Display a settings field
424
+ *
425
+ * @param $field_id
426
+ * @param $field
427
+ */
428
+ function display_field( $field_id, $field ) {
429
+ $value = siteorigin_panels_setting( $field_id );
430
+
431
+ $field_name = 'panels_setting[' . $field_id . ']';
432
+
433
+ switch ( $field['type'] ) {
434
+ case 'text':
435
+ case 'float':
436
+ ?><input name="<?php echo esc_attr( $field_name ) ?>"
437
+ class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>" type="text"
438
+ value="<?php echo esc_attr( $value ) ?>" /> <?php
439
+ break;
440
+
441
+ case 'number':
442
+ ?>
443
+ <input name="<?php echo esc_attr( $field_name ) ?>" type="number"
444
+ class="panels-setting-<?php echo esc_attr( $field['type'] ) ?>"
445
+ value="<?php echo esc_attr( $value ) ?>"/>
446
+ <?php
447
+ if ( ! empty( $field['unit'] ) ) {
448
+ echo esc_html( $field['unit'] );
449
+ }
450
+ break;
451
+
452
+ case 'html':
453
+ ?><textarea name="<?php echo esc_attr( $field_name ) ?>"
454
+ class="panels-setting-<?php echo esc_attr( $field['type'] ) ?> widefat"
455
+ rows="<?php echo ! empty( $field['rows'] ) ? intval( $field['rows'] ) : 2 ?>"><?php echo esc_textarea( $value ) ?></textarea> <?php
456
+ break;
457
+
458
+ case 'checkbox':
459
+ ?>
460
+ <label class="widefat">
461
+ <input name="<?php echo esc_attr( $field_name ) ?>"
462
+ type="checkbox" <?php checked( ! empty( $value ) ) ?> />
463
+ <?php echo ! empty( $field['checkbox_text'] ) ? esc_html( $field['checkbox_text'] ) : __( 'Enabled', 'siteorigin-panels' ) ?>
464
+ </label>
465
+ <?php
466
+ break;
467
+
468
+ case 'select':
469
+ ?>
470
+ <select name="<?php echo esc_attr( $field_name ) ?>">
471
+ <?php foreach ( $field['options'] as $option_id => $option ) : ?>
472
+ <option
473
+ value="<?php echo esc_attr( $option_id ) ?>" <?php selected( $option_id, $value ) ?>><?php echo esc_html( $option ) ?></option>
474
+ <?php endforeach; ?>
475
+ </select>
476
+ <?php
477
+ break;
478
+
479
+ case 'select_multi':
480
+ foreach ( $field['options'] as $option_id => $option ) {
481
+ ?>
482
+ <label class="widefat">
483
+ <input name="<?php echo esc_attr( $field_name ) ?>[<?php echo esc_attr( $option_id ) ?>]"
484
+ type="checkbox" <?php checked( in_array( $option_id, $value ) ) ?> />
485
+ <?php echo esc_html( $option ) ?>
486
+ </label>
487
+ <?php
488
+ }
489
+
490
+ break;
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Save the Page Builder settings.
496
+ */
497
+ function save_settings() {
498
+ $screen = get_current_screen();
499
+ if ( $screen->base != 'settings_page_siteorigin_panels' ) {
500
+ return;
501
+ }
502
+
503
+ if ( ! current_user_can( 'manage_options' ) ) {
504
+ return;
505
+ }
506
+ if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'panels-settings' ) ) {
507
+ return;
508
+ }
509
+ if ( empty( $_POST['panels_setting'] ) ) {
510
+ return;
511
+ }
512
+
513
+ $values = array();
514
+ $post = stripslashes_deep( $_POST['panels_setting'] );
515
+ $settings_fields = $this->fields = apply_filters( 'siteorigin_panels_settings_fields', array() );
516
+
517
+ if ( empty( $settings_fields ) ) {
518
+ return;
519
+ }
520
+
521
+ foreach ( $settings_fields as $section_id => $section ) {
522
+ if ( empty( $section['fields'] ) ) {
523
+ continue;
524
+ }
525
+
526
+ foreach ( $section['fields'] as $field_id => $field ) {
527
+ // Sanitize the fields
528
+ switch ( $field['type'] ) {
529
+ case 'text' :
530
+ $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? sanitize_text_field( $post[ $field_id ] ) : '';
531
+ break;
532
+
533
+ case 'number':
534
+ if ( $post[ $field_id ] != '' ) {
535
+ $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? intval( $post[ $field_id ] ) : 0;
536
+ } else {
537
+ $values[ $field_id ] = '';
538
+ }
539
+ break;
540
+
541
+ case 'float':
542
+ if ( $post[ $field_id ] != '' ) {
543
+ $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? floatval( $post[ $field_id ] ) : 0;
544
+ } else {
545
+ $values[ $field_id ] = '';
546
+ }
547
+ break;
548
+
549
+ case 'html':
550
+ $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
551
+ $values[ $field_id ] = wp_kses_post( $values[ $field_id ] );
552
+ $values[ $field_id ] = force_balance_tags( $values[ $field_id ] );
553
+ break;
554
+
555
+ case 'checkbox':
556
+ $values[ $field_id ] = ! empty( $post[ $field_id ] );
557
+ break;
558
+
559
+ case 'select':
560
+ $values[ $field_id ] = ! empty( $post[ $field_id ] ) ? $post[ $field_id ] : '';
561
+ if ( ! in_array( $values[ $field_id ], array_keys( $field['options'] ) ) ) {
562
+ unset( $values[ $field_id ] );
563
+ }
564
+ break;
565
+
566
+ case 'select_multi':
567
+ $values[ $field_id ] = array();
568
+ $multi_values = array();
569
+ foreach ( $field['options'] as $option_id => $option ) {
570
+ $multi_values[ $option_id ] = ! empty( $post[ $field_id ][ $option_id ] );
571
+ }
572
+ foreach ( $multi_values as $k => $v ) {
573
+ if ( $v ) {
574
+ $values[ $field_id ][] = $k;
575
+ }
576
+ }
577
+
578
+ break;
579
+ }
580
+ }
581
+ }
582
+
583
+ // Don't let mobile width go below 320
584
+ $values[ 'mobile-width' ] = max( $values[ 'mobile-width' ], 320 );
585
+
586
+ // Save the values to the database
587
+ update_option( 'siteorigin_panels_settings', $values );
588
+ do_action( 'siteorigin_panels_save_settings', $values );
589
+ $this->settings = wp_parse_args( $values, $this->settings );
590
+ $this->settings_saved = true;
591
+ }
592
+
593
+ /**
594
+ * Get a post type array
595
+ *
596
+ * @return array
597
+ */
598
+ function get_post_types() {
599
+ $post_types = get_post_types( array( '_builtin' => false ) );
600
+
601
+ $types = array(
602
+ 'page' => 'page',
603
+ 'post' => 'post'
604
+ );
605
+
606
+ // Don't use `array_merge` here as it will break things if a post type has a numeric slug.
607
+ foreach ( $post_types as $key => $value ) {
608
+ $types[ $key ] = $value;
609
+ }
610
+
611
+ // These are post types we know we don't want to show Page Builder on
612
+ unset( $types['ml-slider'] );
613
+
614
+ foreach ( $types as $type_id => $type ) {
615
+ $type_object = get_post_type_object( $type_id );
616
+
617
+ if ( ! $type_object->show_ui ) {
618
+ unset( $types[ $type_id ] );
619
+ continue;
620
+ }
621
+
622
+ $types[ $type_id ] = $type_object->label;
623
+ }
624
+
625
+ return apply_filters( 'siteorigin_panels_settings_enabled_post_types', $types );
626
+ }
627
+
628
+ }
inc/widget-shortcode.php CHANGED
@@ -1,123 +1,123 @@
1
- <?php
2
-
3
- class SiteOrigin_Panels_Widget_Shortcode {
4
-
5
- static $text_widgets = array(
6
- 'SiteOrigin_Widget_Editor_Widget',
7
- 'SiteOrigin_Panels_Widgets_Layout',
8
- 'WP_Widget_Black_Studio_TinyMCE',
9
- 'WP_Widget_Text',
10
- );
11
-
12
- static function init() {
13
- add_shortcode( 'siteorigin_widget', 'SiteOrigin_Panels_Widget_Shortcode::shortcode' );
14
- }
15
-
16
- static function add_filters() {
17
- add_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html', 10, 4 );
18
- }
19
-
20
- static function remove_filters(){
21
- remove_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html' );
22
- }
23
-
24
- /**
25
- * This shortcode just displays a widget based on the given arguments
26
- *
27
- * @param $attr
28
- * @param $content
29
- *
30
- * @return string
31
- */
32
- static function shortcode( $attr, $content ){
33
- $attr = shortcode_atts( array(
34
- 'class' => false,
35
- 'id' => '',
36
- ), $attr, 'siteorigin_widget' );
37
-
38
- $attr[ 'class' ] = html_entity_decode( $attr[ 'class' ] );
39
- $attr[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $attr[ 'class' ] );
40
-
41
- global $wp_widget_factory;
42
- if( ! empty( $attr[ 'class' ] ) && isset( $wp_widget_factory->widgets[ $attr[ 'class' ] ] ) ) {
43
- $the_widget = $wp_widget_factory->widgets[ $attr[ 'class' ] ];
44
-
45
- $data = self::decode_data( $content );
46
-
47
- $widget_args = ! empty( $data[ 'args' ] ) ? $data[ 'args' ] : array();
48
- $widget_instance = ! empty( $data[ 'instance' ] ) ? $data[ 'instance' ] : array();
49
-
50
- $widget_args = wp_parse_args( array(
51
- 'before_widget' => '',
52
- 'after_widget' => '',
53
- 'before_title' => '<h3 class="widget-title">',
54
- 'after_title' => '</h3>',
55
- ), $widget_args );
56
-
57
- ob_start();
58
- $the_widget->widget( $widget_args, $widget_instance );
59
- return ob_get_clean();
60
- }
61
- }
62
-
63
- /**
64
- * Get the shortcode for a specific widget
65
- *
66
- * @param $widget
67
- * @param $args
68
- * @param $instance
69
- *
70
- * @return string
71
- */
72
- static function get_shortcode( $widget, $args, $instance ){
73
- unset( $instance[ 'panels_info' ] );
74
-
75
- $data = array(
76
- 'instance' => $instance,
77
- 'args' => $args,
78
- );
79
-
80
- // This allows other plugins to implement their own shortcode. For example, to work when Page Builder isn't active
81
- $shortcode_name = apply_filters( 'siteorigin_panels_cache_shortcode', 'siteorigin_widget', $widget, $instance, $args );
82
-
83
- $shortcode = '[' . $shortcode_name . ' ';
84
- $shortcode .= 'class="' . htmlentities( preg_replace( '/\\\\+/', '\\\\\\\\', get_class( $widget ) ) ) . '"]';
85
- $shortcode .= self::encode_data( $data ) ;
86
- $shortcode .= '[/' . $shortcode_name . ']';
87
-
88
- return $shortcode;
89
- }
90
-
91
- /**
92
- * A filter to replace widgets with
93
- */
94
- static function widget_html( $html, $widget, $args, $instance ){
95
- if(
96
- empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] ) ||
97
- // Don't try create HTML if there already is some
98
- ! empty( $html ) ||
99
- ! is_object( $widget ) ||
100
- // Skip for known text based widgets
101
- in_array( get_class( $widget ), self::$text_widgets )
102
- ) {
103
- return $html;
104
- }
105
-
106
- return self::get_shortcode( $widget, $args, $instance );
107
- }
108
-
109
- static function encode_data( $data ){
110
- return '<input type="hidden" value="' . htmlentities( json_encode( $data ), ENT_QUOTES ) . '" />';
111
- }
112
-
113
- static function decode_data( $string ){
114
- preg_match( '/value="([^"]*)"/', trim( $string ), $matches );
115
- if( ! empty( $matches[1] ) ) {
116
- $data = json_decode( html_entity_decode( $matches[1], ENT_QUOTES ), true );
117
- return $data;
118
- }
119
- else {
120
- return array();
121
- }
122
- }
123
- }
1
+ <?php
2
+
3
+ class SiteOrigin_Panels_Widget_Shortcode {
4
+
5
+ static $text_widgets = array(
6
+ 'SiteOrigin_Widget_Editor_Widget',
7
+ 'SiteOrigin_Panels_Widgets_Layout',
8
+ 'WP_Widget_Black_Studio_TinyMCE',
9
+ 'WP_Widget_Text',
10
+ );
11
+
12
+ static function init() {
13
+ add_shortcode( 'siteorigin_widget', 'SiteOrigin_Panels_Widget_Shortcode::shortcode' );
14
+ }
15
+
16
+ static function add_filters() {
17
+ add_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html', 10, 4 );
18
+ }
19
+
20
+ static function remove_filters(){
21
+ remove_filter( 'siteorigin_panels_the_widget_html', 'SiteOrigin_Panels_Widget_Shortcode::widget_html' );
22
+ }
23
+
24
+ /**
25
+ * This shortcode just displays a widget based on the given arguments
26
+ *
27
+ * @param $attr
28
+ * @param $content
29
+ *
30
+ * @return string
31
+ */
32
+ static function shortcode( $attr, $content ){
33
+ $attr = shortcode_atts( array(
34
+ 'class' => false,
35
+ 'id' => '',
36
+ ), $attr, 'siteorigin_widget' );
37
+
38
+ $attr[ 'class' ] = html_entity_decode( $attr[ 'class' ] );
39
+ $attr[ 'class' ] = apply_filters( 'siteorigin_panels_widget_class', $attr[ 'class' ] );
40
+
41
+ global $wp_widget_factory;
42
+ if( ! empty( $attr[ 'class' ] ) && isset( $wp_widget_factory->widgets[ $attr[ 'class' ] ] ) ) {
43
+ $the_widget = $wp_widget_factory->widgets[ $attr[ 'class' ] ];
44
+
45
+ $data = self::decode_data( $content );
46
+
47
+ $widget_args = ! empty( $data[ 'args' ] ) ? $data[ 'args' ] : array();
48
+ $widget_instance = ! empty( $data[ 'instance' ] ) ? $data[ 'instance' ] : array();
49
+
50
+ $widget_args = wp_parse_args( array(
51
+ 'before_widget' => '',
52
+ 'after_widget' => '',
53
+ 'before_title' => '<h3 class="widget-title">',
54
+ 'after_title' => '</h3>',
55
+ ), $widget_args );
56
+
57
+ ob_start();
58
+ $the_widget->widget( $widget_args, $widget_instance );
59
+ return ob_get_clean();
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get the shortcode for a specific widget
65
+ *
66
+ * @param $widget
67
+ * @param $args
68
+ * @param $instance
69
+ *
70
+ * @return string
71
+ */
72
+ static function get_shortcode( $widget, $args, $instance ){
73
+ unset( $instance[ 'panels_info' ] );
74
+
75
+ $data = array(
76
+ 'instance' => $instance,
77
+ 'args' => $args,
78
+ );
79
+
80
+ // This allows other plugins to implement their own shortcode. For example, to work when Page Builder isn't active
81
+ $shortcode_name = apply_filters( 'siteorigin_panels_cache_shortcode', 'siteorigin_widget', $widget, $instance, $args );
82
+
83
+ $shortcode = '[' . $shortcode_name . ' ';
84
+ $shortcode .= 'class="' . htmlentities( preg_replace( '/\\\\+/', '\\\\\\\\', get_class( $widget ) ) ) . '"]';
85
+ $shortcode .= self::encode_data( $data ) ;
86
+ $shortcode .= '[/' . $shortcode_name . ']';
87
+
88
+ return $shortcode;
89
+ }
90
+
91
+ /**
92
+ * A filter to replace widgets with
93
+ */
94
+ static function widget_html( $html, $widget, $args, $instance ){
95
+ if(
96
+ empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] ) ||
97
+ // Don't try create HTML if there already is some
98
+ ! empty( $html ) ||
99
+ ! is_object( $widget ) ||
100
+ // Skip for known text based widgets
101
+ in_array( get_class( $widget ), self::$text_widgets )
102
+ ) {
103
+ return $html;
104
+ }
105
+
106
+ return self::get_shortcode( $widget, $args, $instance );
107
+ }
108
+
109
+ static function encode_data( $data ){
110
+ return '<input type="hidden" value="' . htmlentities( json_encode( $data ), ENT_QUOTES ) . '" />';
111
+ }
112
+
113
+ static function decode_data( $string ){
114
+ preg_match( '/value="([^"]*)"/', trim( $string ), $matches );
115
+ if( ! empty( $matches[1] ) ) {
116
+ $data = json_decode( html_entity_decode( $matches[1], ENT_QUOTES ), true );
117
+ return $data;
118
+ }
119
+ else {
120
+ return array();
121
+ }
122
+ }
123
+ }
js/{siteorigin-panels-262.js → siteorigin-panels-263.js} RENAMED
@@ -4820,924 +4820,911 @@ module.exports = Backbone.View.extend( {
4820
  } );
4821
 
4822
  },{}],24:[function(require,module,exports){
4823
- var panels = window.panels, $ = jQuery;
4824
-
4825
- module.exports = Backbone.View.extend( {
4826
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-cell' ).html() ) ),
4827
- events: {
4828
- 'click .cell-wrapper': 'handleCellClick'
4829
- },
4830
-
4831
- /* The row view that this cell is a part of */
4832
- row: null,
4833
- widgetSortable: null,
4834
-
4835
- initialize: function () {
4836
- this.model.get('widgets').on( 'add', this.onAddWidget, this );
4837
- },
4838
-
4839
- /**
4840
- * Render the actual cell
4841
- */
4842
- render: function () {
4843
- var templateArgs = {
4844
- weight: this.model.get( 'weight' ),
4845
- totalWeight: this.row.model.get('cells').totalWeight()
4846
- };
4847
-
4848
- this.setElement( this.template( templateArgs ) );
4849
- this.$el.data( 'view', this );
4850
-
4851
- // Now lets render any widgets that are currently in the row
4852
- var thisView = this;
4853
- this.model.get('widgets').each( function ( widget ) {
4854
- var widgetView = new panels.view.widget( {model: widget} );
4855
- widgetView.cell = thisView;
4856
- widgetView.render();
4857
-
4858
- widgetView.$el.appendTo( thisView.$( '.widgets-container' ) );
4859
- } );
4860
-
4861
- this.initSortable();
4862
- this.initResizable();
4863
-
4864
- return this;
4865
- },
4866
-
4867
- /**
4868
- * Initialize the widget sortable
4869
- */
4870
- initSortable: function () {
4871
- if( ! this.row.builder.supports( 'moveWidget' ) ) {
4872
- return this;
4873
- }
4874
-
4875
- var cellView = this;
4876
-
4877
- // Go up the view hierarchy until we find the ID attribute
4878
- var builderID = cellView.row.builder.$el.attr( 'id' );
4879
-
4880
- // Create a widget sortable that's connected with all other cells
4881
- this.widgetSortable = this.$( '.widgets-container' ).sortable( {
4882
- placeholder: "so-widget-sortable-highlight",
4883
- connectWith: '#' + builderID + ' .so-cells .cell .widgets-container',
4884
- tolerance: 'pointer',
4885
- scroll: false,
4886
- over: function ( e, ui ) {
4887
- // This will make all the rows in the current builder resize
4888
- cellView.row.builder.trigger( 'widget_sortable_move' );
4889
- },
4890
- stop: function ( e, ui ) {
4891
- cellView.row.builder.addHistoryEntry( 'widget_moved' );
4892
-
4893
- var $$ = $( ui.item ),
4894
- widget = $$.data( 'view' ),
4895
- targetCell = $$.closest( '.cell' ).data( 'view' );
4896
-
4897
- // Move the model and the view to the new cell
4898
- widget.model.moveToCell( targetCell.model, {}, $$.index() );
4899
- widget.cell = targetCell;
4900
-
4901
- widget.cell.row.builder.model.refreshPanelsData();
4902
- },
4903
- helper: function ( e, el ) {
4904
- var helper = el.clone()
4905
- .css( {
4906
- 'width': el.outerWidth(),
4907
- 'z-index': 10000,
4908
- 'position': 'fixed'
4909
- } )
4910
- .addClass( 'widget-being-dragged' ).appendTo( 'body' );
4911
-
4912
- // Center the helper to the mouse cursor.
4913
- if ( el.outerWidth() > 720 ) {
4914
- helper.animate( {
4915
- 'margin-left': e.pageX - el.offset().left - (
4916
- 480 / 2
4917
- ),
4918
- 'width': 480
4919
- }, 'fast' );
4920
- }
4921
-
4922
- return helper;
4923
- }
4924
- } );
4925
-
4926
- return this;
4927
- },
4928
-
4929
- /**
4930
- * Refresh the widget sortable when a new widget is added
4931
- */
4932
- refreshSortable: function () {
4933
- if ( ! _.isNull( this.widgetSortable ) ) {
4934
- this.widgetSortable.sortable( 'refresh' );
4935
- }
4936
- },
4937
-
4938
- /**
4939
- * This will make the cell resizble
4940
- */
4941
- initResizable: function () {
4942
- if( ! this.row.builder.supports( 'editRow' ) ) {
4943
- return this;
4944
- }
4945
-
4946
- // var neighbor = this.$el.previous().data('view');
4947
- var handle = this.$( '.resize-handle' ).css( 'position', 'absolute' );
4948
- var container = this.row.$el;
4949
- var cellView = this;
4950
-
4951
- // The view of the cell to the left is stored when dragging starts.
4952
- var previousCell;
4953
-
4954
- handle.draggable( {
4955
- axis: 'x',
4956
- containment: container,
4957
- start: function ( e, ui ) {
4958
- // Set the containment to the cell parent
4959
- previousCell = cellView.$el.prev().data( 'view' );
4960
- if ( _.isUndefined( previousCell ) ) {
4961
- return;
4962
- }
4963
-
4964
- // Create the clone for the current cell
4965
- var newCellClone = cellView.$el.clone().appendTo( ui.helper ).css( {
4966
- position: 'absolute',
4967
- top: '0',
4968
- width: cellView.$el.outerWidth(),
4969
- left: 5,
4970
- height: cellView.$el.outerHeight()
4971
- } );
4972
- newCellClone.find( '.resize-handle' ).remove();
4973
-
4974
- // Create the clone for the previous cell
4975
- var prevCellClone = previousCell.$el.clone().appendTo( ui.helper ).css( {
4976
- position: 'absolute',
4977
- top: '0',
4978
- width: previousCell.$el.outerWidth(),
4979
- right: 5,
4980
- height: previousCell.$el.outerHeight()
4981
- } );
4982
- prevCellClone.find( '.resize-handle' ).remove();
4983
-
4984
- $( this ).data( {
4985
- 'newCellClone': newCellClone,
4986
- 'prevCellClone': prevCellClone
4987
- } );
4988
- },
4989
- drag: function ( e, ui ) {
4990
- // Calculate the new cell and previous cell widths as a percent
4991
- var containerWidth = cellView.row.$el.width() + 10;
4992
- var ncw = cellView.model.get( 'weight' ) - (
4993
- (
4994
- ui.position.left + handle.outerWidth() / 2
4995
- ) / containerWidth
4996
- );
4997
- var pcw = previousCell.model.get( 'weight' ) + (
4998
- (
4999
- ui.position.left + handle.outerWidth() / 2
5000
- ) / containerWidth
5001
- );
5002
-
5003
- $( this ).data( 'newCellClone' ).css( 'width', containerWidth * ncw )
5004
- .find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
5005
-
5006
- $( this ).data( 'prevCellClone' ).css( 'width', containerWidth * pcw )
5007
- .find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
5008
- },
5009
- stop: function ( e, ui ) {
5010
- // Remove the clones
5011
- $( this ).data( 'newCellClone' ).remove();
5012
- $( this ).data( 'prevCellClone' ).remove();
5013
-
5014
- var containerWidth = cellView.row.$el.width() + 10;
5015
- var ncw = cellView.model.get( 'weight' ) - (
5016
- (
5017
- ui.position.left + handle.outerWidth() / 2
5018
- ) / containerWidth
5019
- );
5020
- var pcw = previousCell.model.get( 'weight' ) + (
5021
- (
5022
- ui.position.left + handle.outerWidth() / 2
5023
- ) / containerWidth
5024
- );
5025
-
5026
- if ( ncw > 0.02 && pcw > 0.02 ) {
5027
- cellView.row.builder.addHistoryEntry( 'cell_resized' );
5028
- cellView.model.set( 'weight', ncw );
5029
- previousCell.model.set( 'weight', pcw );
5030
- cellView.row.resize();
5031
- }
5032
-
5033
- ui.helper.css( 'left', - handle.outerWidth() / 2 );
5034
-
5035
- // Refresh the panels data
5036
- cellView.row.builder.model.refreshPanelsData();
5037
- }
5038
- } );
5039
-
5040
- return this;
5041
- },
5042
-
5043
- /**
5044
- * This is triggered when ever a widget is added to the row collection.
5045
- *
5046
- * @param widget
5047
- */
5048
- onAddWidget: function ( widget, collection, options ) {
5049
- options = _.extend( {noAnimate: false}, options );
5050
-
5051
- // Create the view for the widget
5052
- var view = new panels.view.widget( {
5053
- model: widget
5054
- } );
5055
- view.cell = this;
5056
-
5057
- if ( _.isUndefined( widget.isDuplicate ) ) {
5058
- widget.isDuplicate = false;
5059
- }
5060
-
5061
- // Render and load the form if this is a duplicate
5062
- view.render( {
5063
- 'loadForm': widget.isDuplicate
5064
- } );
5065
-
5066
- if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
5067
- // Insert this at the end of the widgets container
5068
- view.$el.appendTo( this.$( '.widgets-container' ) );
5069
- } else {
5070
- // We need to insert this at a specific position
5071
- view.$el.insertAfter(
5072
- this.$( '.widgets-container .so-widget' ).eq( options.at - 1 )
5073
- );
5074
- }
5075
-
5076
- if ( options.noAnimate === false ) {
5077
- // We need an animation
5078
- view.visualCreate();
5079
- }
5080
-
5081
- this.refreshSortable();
5082
- this.row.resize();
5083
- },
5084
-
5085
- /**
5086
- * Handle this cell being clicked on
5087
- *
5088
- * @param e
5089
- * @returns {boolean}
5090
- */
5091
- handleCellClick: function ( e ) {
5092
- // Remove all existing selected cell indication for this builder
5093
- this.row.builder.$el.find( '.so-cells .cell' ).removeClass( 'cell-selected' );
5094
-
5095
- if( this.row.builder.activeCell === this && ! this.model.get('widgets').length ) {
5096
- // This is a click on an empty cell
5097
- this.row.builder.activeCell = null;
5098
- }
5099
- else {
5100
- this.$el.addClass( 'cell-selected' );
5101
- this.row.builder.activeCell = this;
5102
- }
5103
- },
5104
-
5105
- /**
5106
- * Insert a widget from the clipboard
5107
- */
5108
- pasteHandler: function(){
5109
- var pastedModel = panels.helpers.clipboard.getModel( 'widget-model' );
5110
- if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.widget ) {
5111
- this.row.builder.addHistoryEntry( 'widget_pasted' );
5112
- pastedModel.cell = this.model;
5113
- this.model.get('widgets').add( pastedModel );
5114
- this.row.builder.model.refreshPanelsData();
5115
- }
5116
- },
5117
-
5118
- /**
5119
- * Build up the contextual menu for a cell
5120
- *
5121
- * @param e
5122
- * @param menu
5123
- */
5124
- buildContextualMenu: function ( e, menu ) {
5125
- var thisView = this;
5126
-
5127
- if( ! menu.hasSection( 'add-widget-below' ) ) {
5128
- menu.addSection(
5129
- 'add-widget-cell',
5130
- {
5131
- sectionTitle: panelsOptions.loc.contextual.add_widget_cell,
5132
- searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
5133
- defaultDisplay: panelsOptions.contextual.default_widgets
5134
- },
5135
- panelsOptions.widgets,
5136
- function ( c ) {
5137
- thisView.row.builder.addHistoryEntry( 'widget_added' );
5138
-
5139
- var widget = new panels.model.widget( {
5140
- class: c
5141
- } );
5142
-
5143
- // Add the widget to the cell model
5144
- widget.cell = thisView.model;
5145
- widget.cell.get('widgets').add( widget );
5146
-
5147
- thisView.row.builder.model.refreshPanelsData();
5148
- }
5149
- );
5150
- }
5151
-
5152
- var actions = {};
5153
- if ( this.row.builder.supports('addWidget') && panels.helpers.clipboard.isModel( 'widget-model' ) ) {
5154
- actions.paste = {title: panelsOptions.loc.contextual.cell_paste_widget};
5155
- }
5156
-
5157
- if( ! _.isEmpty( actions ) ) {
5158
- menu.addSection(
5159
- 'cell-actions',
5160
- {
5161
- sectionTitle: panelsOptions.loc.contextual.cell_actions,
5162
- search: false,
5163
- },
5164
- actions,
5165
- function ( c ) {
5166
- switch ( c ) {
5167
- case 'paste':
5168
- this.pasteHandler();
5169
- break;
5170
- }
5171
-
5172
- this.row.builder.model.refreshPanelsData();
5173
- }.bind( this )
5174
- );
5175
- }
5176
-
5177
- // Add the contextual menu for the parent row
5178
- this.row.buildContextualMenu( e, menu );
5179
- }
5180
- } );
5181
-
5182
- },{}],25:[function(require,module,exports){
5183
- var panels = window.panels, $ = jQuery;
5184
-
5185
- module.exports = Backbone.View.extend( {
5186
- dialogTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog' ).html() ) ),
5187
- dialogTabTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-tab' ).html() ) ),
5188
-
5189
- tabbed: false,
5190
- rendered: false,
5191
- builder: false,
5192
- className: 'so-panels-dialog-wrapper',
5193
- dialogClass: '',
5194
- dialogIcon: '',
5195
- parentDialog: false,
5196
- dialogOpen: false,
5197
- editableLabel: false,
5198
-
5199
- events: {
5200
- 'click .so-close': 'closeDialog',
5201
- 'click .so-nav.so-previous': 'navToPrevious',
5202
- 'click .so-nav.so-next': 'navToNext',
5203
- },
5204
-
5205
- initialize: function () {
5206
- // The first time this dialog is opened, render it
5207
- this.once( 'open_dialog', this.render );
5208
- this.once( 'open_dialog', this.attach );
5209
- this.once( 'open_dialog', this.setDialogClass );
5210
-
5211
- this.trigger( 'initialize_dialog', this );
5212
-
5213
- if ( ! _.isUndefined( this.initializeDialog ) ) {
5214
- this.initializeDialog();
5215
- }
5216
- },
5217
-
5218
- /**
5219
- * Returns the next dialog in the sequence. Should be overwritten by a child dialog.
5220
- * @returns {null}
5221
- */
5222
- getNextDialog: function () {
5223
- return null;
5224
- },
5225
-
5226
- /**
5227
- * Returns the previous dialog in this sequence. Should be overwritten by child dialog.
5228
- * @returns {null}
5229
- */
5230
- getPrevDialog: function () {
5231
- return null;
5232
- },
5233
-
5234
- /**
5235
- * Adds a dialog class to uniquely identify this dialog type
5236
- */
5237
- setDialogClass: function () {
5238
- if ( this.dialogClass !== '' ) {
5239
- this.$( '.so-panels-dialog' ).addClass( this.dialogClass );
5240
- }
5241
- },
5242
-
5243
- /**
5244
- * Set the builder that controls this dialog.
5245
- * @param {panels.view.builder} builder
5246
- */
5247
- setBuilder: function ( builder ) {
5248
- this.builder = builder;
5249
-
5250
- // Trigger an add dialog event on the builder so it can modify the dialog in any way
5251
- builder.trigger( 'add_dialog', this, this.builder );
5252
-
5253
- return this;
5254
- },
5255
-
5256
- /**
5257
- * Attach the dialog to the window
5258
- */
5259
- attach: function () {
5260
- this.$el.appendTo( 'body' );
5261
-
5262
- return this;
5263
- },
5264
-
5265
- /**
5266
- * Converts an HTML representation of the dialog into arguments for a dialog box
5267
- * @param html HTML for the dialog
5268
- * @param args Arguments passed to the template
5269
- * @returns {}
5270
- */
5271
- parseDialogContent: function ( html, args ) {
5272
- // Add a CID
5273
- args = _.extend( {cid: this.cid}, args );
5274
-
5275
-
5276
- var c = $( (
5277
- _.template( panels.helpers.utils.processTemplate( html ) )
5278
- )( args ) );
5279
- var r = {
5280
- title: c.find( '.title' ).html(),
5281
- buttons: c.find( '.buttons' ).html(),
5282
- content: c.find( '.content' ).html()
5283
- };
5284
-
5285
- if ( c.has( '.left-sidebar' ) ) {
5286
- r.left_sidebar = c.find( '.left-sidebar' ).html();
5287
- }
5288
-
5289
- if ( c.has( '.right-sidebar' ) ) {
5290
- r.right_sidebar = c.find( '.right-sidebar' ).html();
5291
- }
5292
-
5293
- return r;
5294
-
5295
- },
5296
-
5297
- /**
5298
- * Render the dialog and initialize the tabs
5299
- *
5300
- * @param attributes
5301
- * @returns {panels.view.dialog}
5302
- */
5303
- renderDialog: function ( attributes ) {
5304
- attributes = _.extend( {
5305
- editableLabel: this.editableLabel,
5306
- dialogIcon: this.dialogIcon,
5307
- }, attributes );
5308
-
5309
- this.$el.html( this.dialogTemplate( attributes ) ).hide();
5310
- this.$el.data( 'view', this );
5311
- this.$el.addClass( 'so-panels-dialog-wrapper' );
5312
-
5313
- if ( this.parentDialog !== false ) {
5314
- // Add a link to the parent dialog as a sort of crumbtrail.
5315
- var thisDialog = this;
5316
- var dialogParent = $( '<h3 class="so-parent-link"></h3>' ).html( this.parentDialog.text + '<div class="so-separator"></div>' );
5317
- dialogParent.click( function ( e ) {
5318
- e.preventDefault();
5319
- thisDialog.closeDialog();
5320
- thisDialog.parentDialog.openDialog();
5321
- } );
5322
- this.$( '.so-title-bar' ).prepend( dialogParent );
5323
- }
5324
-
5325
- if( this.$( '.so-title-bar .so-title-editable' ).length ) {
5326
- // Added here because .so-edit-title is only available after the template has been rendered.
5327
- this.initEditableLabel();
5328
- }
5329
-
5330
- return this;
5331
- },
5332
-
5333
- /**
5334
- * Initialize the sidebar tabs
5335
- */
5336
- initTabs: function () {
5337
- var tabs = this.$( '.so-sidebar-tabs li a' );
5338
-
5339
- if ( tabs.length === 0 ) {
5340
- return this;
5341
- }
5342
-
5343
- var thisDialog = this;
5344
- tabs.click( function ( e ) {
5345
- e.preventDefault();
5346
- var $$ = $( this );
5347
-
5348
- thisDialog.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
5349
- thisDialog.$( '.so-content .so-content-tabs > *' ).hide();
5350
-
5351
- $$.parent().addClass( 'tab-active' );
5352
-
5353
- var url = $$.attr( 'href' );
5354
- if ( ! _.isUndefined( url ) && url.charAt( 0 ) === '#' ) {
5355
- // Display the new tab
5356
- var tabName = url.split( '#' )[1];
5357
- thisDialog.$( '.so-content .so-content-tabs .tab-' + tabName ).show();
5358
- }
5359
-
5360
- // This lets other dialogs implement their own custom handlers
5361
- thisDialog.trigger( 'tab_click', $$ );
5362
-
5363
- } );
5364
-
5365
- // Trigger a click on the first tab
5366
- this.$( '.so-sidebar-tabs li a' ).first().click();
5367
- return this;
5368
- },
5369
-
5370
- initToolbar: function () {
5371
- // Trigger simplified click event for elements marked as toolbar buttons.
5372
- var buttons = this.$( '.so-toolbar .so-buttons .so-toolbar-button' );
5373
- buttons.click( function ( e ) {
5374
- e.preventDefault();
5375
-
5376
- this.trigger( 'button_click', $( e.currentTarget ) );
5377
- }.bind( this ) );
5378
-
5379
- // Handle showing and hiding the dropdown list items
5380
- var $dropdowns = this.$( '.so-toolbar .so-buttons .so-dropdown-button' );
5381
- $dropdowns.click( function ( e ) {
5382
- e.preventDefault();
5383
- var $dropdownButton = $( e.currentTarget );
5384
- var $dropdownList = $dropdownButton.siblings( '.so-dropdown-links-wrapper' );
5385
- if ( $dropdownList.is( '.hidden' ) ) {
5386
- $dropdownList.removeClass( 'hidden' );
5387
- } else {
5388
- $dropdownList.addClass( 'hidden' );
5389
- }
5390
-
5391
- }.bind( this ) );
5392
-
5393
- // Hide dropdown list on click anywhere, unless it's a dropdown option which requires confirmation in it's
5394
- // unconfirmed state.
5395
- $( 'html' ).click( function ( e ) {
5396
- this.$( '.so-dropdown-links-wrapper' ).not( '.hidden' ).each( function ( index, el ) {
5397
- var $dropdownList = $( el );
5398
- var $trgt = $( e.target );
5399
- if ( $trgt.length === 0 || !(
5400
- (
5401
- $trgt.is('.so-needs-confirm') && !$trgt.is('.so-confirmed')
5402
- ) || $trgt.is('.so-dropdown-button')
5403
- ) ) {
5404
- $dropdownList.addClass('hidden');
5405
- }
5406
- } );
5407
- }.bind( this ) );
5408
- },
5409
-
5410
- /**
5411
- * Initialize the editable dialog title
5412
- */
5413
- initEditableLabel: function(){
5414
- var $editElt = this.$( '.so-title-bar .so-title-editable' );
5415
-
5416
- $editElt.keypress( function ( event ) {
5417
- var enterPressed = event.type === 'keypress' && event.keyCode === 13;
5418
- if ( enterPressed ) {
5419
- // Need to make sure tab focus is on another element, otherwise pressing enter multiple times refocuses
5420
- // the element and allows newlines.
5421
- var tabbables = $( ':tabbable' );
5422
- var curTabIndex = tabbables.index( $editElt );
5423
- tabbables.eq( curTabIndex + 1 ).focus();
5424
- // After the above, we're somehow left with the first letter of text selected,
5425
- // so this removes the selection.
5426
- window.getSelection().removeAllRanges();
5427
- }
5428
- return !enterPressed;
5429
- } ).blur( function () {
5430
- var newValue = $editElt.text().replace( /^\s+|\s+$/gm, '' );
5431
- var oldValue = $editElt.data( 'original-value' ).replace( /^\s+|\s+$/gm, '' );
5432
- if ( newValue !== oldValue ) {
5433
- $editElt.text( newValue );
5434
- this.trigger( 'edit_label', newValue );
5435
- }
5436
-
5437
- }.bind( this ) );
5438
-
5439
- $editElt.focus( function() {
5440
- $editElt.data( 'original-value', $editElt.text() );
5441
- panels.helpers.utils.selectElementContents( this );
5442
- } );
5443
- },
5444
-
5445
- /**
5446
- * Quickly setup the dialog by opening and closing it.
5447
- */
5448
- setupDialog: function () {
5449
- this.openDialog();
5450
- this.closeDialog();
5451
- },
5452
-
5453
- /**
5454
- * Refresh the next and previous buttons.
5455
- */
5456
- refreshDialogNav: function () {
5457
- this.$( '.so-title-bar .so-nav' ).show().removeClass( 'so-disabled' );
5458
-
5459
- // Lets also hide the next and previous if we don't have a next and previous dialog
5460
- var nextDialog = this.getNextDialog();
5461
- var nextButton = this.$( '.so-title-bar .so-next' );
5462
-
5463
- var prevDialog = this.getPrevDialog();
5464
- var prevButton = this.$( '.so-title-bar .so-previous' );
5465
-
5466
- if ( nextDialog === null ) {
5467
- nextButton.hide();
5468
- }
5469
- else if ( nextDialog === false ) {
5470
- nextButton.addClass( 'so-disabled' );
5471
- }
5472
-
5473
- if ( prevDialog === null ) {
5474
- prevButton.hide();
5475
- }
5476
- else if ( prevDialog === false ) {
5477
- prevButton.addClass( 'so-disabled' );
5478
- }
5479
- },
5480
-
5481
- /**
5482
- * Open the dialog
5483
- */
5484
- openDialog: function ( options ) {
5485
- options = _.extend( {
5486
- silent: false
5487
- }, options );
5488
-
5489
- if ( ! options.silent ) {
5490
- this.trigger( 'open_dialog' );
5491
- }
5492
-
5493
- this.dialogOpen = true;
5494
-
5495
- this.refreshDialogNav();
5496
-
5497
- // Stop scrolling for the main body
5498
- panels.helpers.pageScroll.lock();
5499
-
5500
- // Start listen for keyboard keypresses.
5501
- $( window ).on( 'keyup', this.keyboardListen );
5502
-
5503
- this.$el.show();
5504
-
5505
- if ( ! options.silent ) {
5506
- // This triggers once everything is visible
5507
- this.trigger( 'open_dialog_complete' );
5508
- this.builder.trigger( 'open_dialog', this );
5509
- $( document ).trigger( 'open_dialog', this );
5510
- }
5511
- },
5512
-
5513
- /**
5514
- * Close the dialog
5515
- *
5516
- * @param e
5517
- * @returns {boolean}
5518
- */
5519
- closeDialog: function ( options ) {
5520
- options = _.extend( {
5521
- silent: false
5522
- }, options );
5523
-
5524
- if ( ! options.silent ) {
5525
- this.trigger( 'close_dialog' );
5526
- }
5527
-
5528
- this.dialogOpen = false;
5529
-
5530
- this.$el.hide();
5531
- panels.helpers.pageScroll.unlock();
5532
-
5533
- // Stop listen for keyboard keypresses.
5534
- $( window ).off( 'keyup', this.keyboardListen );
5535
-
5536
- if ( ! options.silent ) {
5537
- // This triggers once everything is hidden
5538
- this.trigger( 'close_dialog_complete' );
5539
- this.builder.trigger( 'close_dialog', this );
5540
- }
5541
- },
5542
-
5543
- /**
5544
- * Keyboard events handler
5545
- */
5546
- keyboardListen: function ( e ) {
5547
- // [Esc] to close
5548
- if ( e.which === 27 ) {
5549
- $( '.so-panels-dialog-wrapper .so-close' ).trigger( 'click' );
5550
- }
5551
- },
5552
-
5553
- /**
5554
- * Navigate to the previous dialog
5555
- */
5556
- navToPrevious: function () {
5557
- this.closeDialog();
5558
-
5559
- var prev = this.getPrevDialog();
5560
- if ( prev !== null && prev !== false ) {
5561
- prev.openDialog();
5562
- }
5563
- },
5564
-
5565
- /**
5566
- * Navigate to the next dialog
5567
- */
5568
- navToNext: function () {
5569
- this.closeDialog();
5570
-
5571
- var next = this.getNextDialog();
5572
- if ( next !== null && next !== false ) {
5573
- next.openDialog();
5574
- }
5575
- },
5576
-
5577
- /**
5578
- * Get the values from the form and convert them into a data array
5579
- */
5580
- getFormValues: function ( formSelector ) {
5581
- if ( _.isUndefined( formSelector ) ) {
5582
- formSelector = '.so-content';
5583
- }
5584
-
5585
- var $f = this.$( formSelector );
5586
-
5587
- var data = {}, parts;
5588
-
5589
- // Find all the named fields in the form
5590
- $f.find( '[name]' ).each( function () {
5591
- var $$ = $( this );
5592
-
5593
- try {
5594
-
5595
- var name = /([A-Za-z_]+)\[(.*)\]/.exec( $$.attr( 'name' ) );
5596
- if ( _.isEmpty( name ) ) {
5597
- return true;
5598
- }
5599
-
5600
- // Create an array with the parts of the name
5601
- if ( _.isUndefined( name[2] ) ) {
5602
- parts = $$.attr( 'name' );
5603
- } else {
5604
- parts = name[2].split( '][' );
5605
- parts.unshift( name[1] );
5606
- }
5607
-
5608
- parts = parts.map( function ( e ) {
5609
- if ( ! isNaN( parseFloat( e ) ) && isFinite( e ) ) {
5610
- return parseInt( e );
5611
- } else {
5612
- return e;
5613
- }
5614
- } );
5615
-
5616
- var sub = data;
5617
- var fieldValue = null;
5618
-
5619
- var fieldType = (
5620
- _.isString( $$.attr( 'type' ) ) ? $$.attr( 'type' ).toLowerCase() : false
5621
- );
5622
-
5623
- // First we need to get the value from the field
5624
- if ( fieldType === 'checkbox' ) {
5625
- if ( $$.is( ':checked' ) ) {
5626
- fieldValue = $$.val() !== '' ? $$.val() : true;
5627
- } else {
5628
- fieldValue = null;
5629
- }
5630
- }
5631
- else if ( fieldType === 'radio' ) {
5632
- if ( $$.is( ':checked' ) ) {
5633
- fieldValue = $$.val();
5634
- } else {
5635
- //skip over unchecked radios
5636
- return;
5637
- }
5638
- }
5639
- else if ( $$.prop( 'tagName' ) === 'TEXTAREA' && $$.hasClass( 'wp-editor-area' ) ) {
5640
- // This is a TinyMCE editor, so we'll use the tinyMCE object to get the content
5641
- var editor = null;
5642
- if ( typeof tinyMCE !== 'undefined' ) {
5643
- editor = tinyMCE.get( $$.attr( 'id' ) );
5644
- }
5645
-
5646
- if ( editor !== null && _.isFunction( editor.getContent ) && ! editor.isHidden() ) {
5647
- fieldValue = editor.getContent();
5648
- } else {
5649
- fieldValue = $$.val();
5650
- }
5651
- }
5652
- else if ( $$.prop( 'tagName' ) === 'SELECT' ) {
5653
- var selected = $$.find( 'option:selected' );
5654
-
5655
- if ( selected.length === 1 ) {
5656
- fieldValue = $$.find( 'option:selected' ).val();
5657
- }
5658
- else if ( selected.length > 1 ) {
5659
- // This is a mutli-select field
5660
- fieldValue = _.map( $$.find( 'option:selected' ), function ( n, i ) {
5661
- return $( n ).val();
5662
- } );
5663
- }
5664
-
5665
- } else {
5666
- // This is a fallback that will work for most fields
5667
- fieldValue = $$.val();
5668
- }
5669
-
5670
- // Now, we need to filter this value if necessary
5671
- if ( ! _.isUndefined( $$.data( 'panels-filter' ) ) ) {
5672
- switch ( $$.data( 'panels-filter' ) ) {
5673
- case 'json_parse':
5674
- // Attempt to parse the JSON value of this field
5675
- try {
5676
- fieldValue = JSON.parse( fieldValue );
5677
- }
5678
- catch ( err ) {
5679
- fieldValue = '';
5680
- }
5681
- break;
5682
- }
5683
- }
5684
-
5685
- // Now convert this into an array
5686
- if ( fieldValue !== null ) {
5687
- for ( var i = 0; i < parts.length; i ++ ) {
5688
- if ( i === parts.length - 1 ) {
5689
- if ( parts[i] === '' ) {
5690
- // This needs to be an array
5691
- sub.push( fieldValue );
5692
- } else {
5693
- sub[parts[i]] = fieldValue;
5694
- }
5695
- } else {
5696
- if ( _.isUndefined( sub[parts[i]] ) ) {
5697
- if ( parts[i + 1] === '' ) {
5698
- sub[parts[i]] = [];
5699
- } else {
5700
- sub[parts[i]] = {};
5701
- }
5702
- }
5703
- sub = sub[parts[i]];
5704
- }
5705
- }
5706
- }
5707
- }
5708
- catch ( error ) {
5709
- // Ignore this error, just log the message for debugging
5710
- console.log( 'Field [' + $$.attr('name') + '] could not be processed and was skipped - ' + error.message );
5711
- }
5712
-
5713
- } ); // End of each through input fields
5714
-
5715
- return data;
5716
- },
5717
-
5718
- /**
5719
- * Set a status message for the dialog
5720
- */
5721
- setStatusMessage: function ( message, loading, error ) {
5722
- var msg = error ? '<span class="dashicons dashicons-warning"></span>' + message : message;
5723
- this.$( '.so-toolbar .so-status' ).html( msg );
5724
- if ( ! _.isUndefined( loading ) && loading ) {
5725
- this.$( '.so-toolbar .so-status' ).addClass( 'so-panels-loading' );
5726
- } else {
5727
- this.$( '.so-toolbar .so-status' ).removeClass( 'so-panels-loading' );
5728
- }
5729
- },
5730
 
5731
- /**
5732
- * Set the parent after.
5733
- */
5734
- setParent: function ( text, dialog ) {
5735
- this.parentDialog = {
5736
- text: text,
5737
- dialog: dialog
5738
- };
5739
- }
5740
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5741
 
5742
  },{}],26:[function(require,module,exports){
5743
  var panels = window.panels, $ = jQuery;
@@ -6153,415 +6140,415 @@ module.exports = Backbone.View.extend( {
6153
  } );
6154
 
6155
  },{}],27:[function(require,module,exports){
6156
- var panels = window.panels, $ = jQuery;
6157
-
6158
- module.exports = Backbone.View.extend( {
6159
- template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-row' ).html() ) ),
6160
-
6161
- events: {
6162
- 'click .so-row-settings': 'editSettingsHandler',
6163
- 'click .so-row-duplicate': 'duplicateHandler',
6164
- 'click .so-row-delete': 'confirmedDeleteHandler',
6165
- 'click .so-row-color': 'rowColorChangeHandler',
6166
- },
6167
-
6168
- builder: null,
6169
- dialog: null,
6170
-
6171
- /**
6172
- * Initialize the row view
6173
- */
6174
- initialize: function () {
6175
-
6176
- var rowCells = this.model.get('cells');
6177
- rowCells.on( 'add', this.handleCellAdd, this );
6178
- rowCells.on( 'remove', this.handleCellRemove, this );
6179
- this.model.on( 'reweight_cells', this.resize, this );
6180
-
6181
- this.model.on( 'destroy', this.onModelDestroy, this );
6182
- this.model.on( 'visual_destroy', this.visualDestroyModel, this );
6183
-
6184
- var thisView = this;
6185
- rowCells.each( function ( cell ) {
6186
- thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6187
- } );
6188
-
6189
- // When ever a new cell is added, listen to it for new widgets
6190
- rowCells.on( 'add', function ( cell ) {
6191
- thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6192
- }, this );
6193
-
6194
- this.model.on( 'change:label', this.onLabelChange, this );
6195
- },
6196
-
6197
- /**
6198
- * Render the row.
6199
- *
6200
- * @returns {panels.view.row}
6201
- */
6202
- render: function () {
6203
- var rowColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6204
- var rowLabel = this.model.has( 'label' ) ? this.model.get( 'label' ) : '';
6205
- this.setElement( this.template( { rowColorLabel: rowColorLabel, rowLabel: rowLabel } ) );
6206
- this.$el.data( 'view', this );
6207
-
6208
- // Create views for the cells in this row
6209
- var thisView = this;
6210
- this.model.get('cells').each( function ( cell ) {
6211
- var cellView = new panels.view.cell( {
6212
- model: cell
6213
- } );
6214
- cellView.row = thisView;
6215
- cellView.render();
6216
- cellView.$el.appendTo( thisView.$( '.so-cells' ) );
6217
- } );
6218
-
6219
- // Remove any unsupported actions
6220
- if( ! this.builder.supports( 'rowAction' ) ) {
6221
- this.$('.so-row-toolbar .so-dropdown-wrapper' ).remove();
6222
- this.$el.addClass('so-row-no-actions');
6223
- }
6224
- else {
6225
- if( ! this.builder.supports( 'editRow' ) ) {
6226
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-settings' ).parent().remove();
6227
- this.$el.addClass('so-row-no-edit');
6228
- }
6229
- if( ! this.builder.supports( 'addRow' ) ) {
6230
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate' ).parent().remove();
6231
- this.$el.addClass('so-row-no-duplicate');
6232
- }
6233
- if( ! this.builder.supports( 'deleteRow' ) ) {
6234
- this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-delete' ).parent().remove();
6235
- this.$el.addClass('so-row-no-delete');
6236
- }
6237
- }
6238
- if( ! this.builder.supports( 'moveRow' ) ) {
6239
- this.$('.so-row-toolbar .so-row-move' ).remove();
6240
- this.$el.addClass('so-row-no-move');
6241
- }
6242
- if( !$.trim( this.$('.so-row-toolbar').html() ).length ) {
6243
- this.$('.so-row-toolbar' ).remove();
6244
- }
6245
-
6246
- // Resize the rows when ever the widget sortable moves
6247
- this.builder.on( 'widget_sortable_move', this.resize, this );
6248
- this.builder.on( 'builder_resize', this.resize, this );
6249
-
6250
- this.resize();
6251
-
6252
- return this;
6253
- },
6254
-
6255
- /**
6256
- * Give a visual indication of the creation of this row
6257
- */
6258
- visualCreate: function () {
6259
- this.$el.hide().fadeIn( 'fast' );
6260
- },
6261
-
6262
- /**
6263
- * Visually resize the row so that all cell heights are the same and the widths so that they balance to 100%
6264
- *
6265
- * @param e
6266
- */
6267
- resize: function ( e ) {
6268
- // Don't resize this
6269
- if ( ! this.$el.is( ':visible' ) ) {
6270
- return;
6271
- }
6272
-
6273
- // Reset everything to have an automatic height
6274
- this.$( '.so-cells .cell-wrapper' ).css( 'min-height', 0 );
6275
- this.$( '.so-cells .resize-handle' ).css( 'height', 0 );
6276
-
6277
- // We'll tie the values to the row view, to prevent issue with values going to different rows
6278
- var height = 0;
6279
- this.$( '.so-cells .cell' ).each( function () {
6280
- height = Math.max(
6281
- height,
6282
- $( this ).height()
6283
- );
6284
-
6285
- $( this ).css(
6286
- 'width',
6287
- ( $( this ).data( 'view' ).model.get( 'weight' ) * 100) + "%"
6288
- );
6289
- } );
6290
-
6291
- // Resize all the grids and cell wrappers
6292
- this.$( '.so-cells .cell-wrapper' ).css( 'min-height', Math.max( height, 63 ) );
6293
- this.$( '.so-cells .resize-handle' ).css( 'height', this.$( '.so-cells .cell-wrapper' ).outerHeight() );
6294
- },
6295
-
6296
- /**
6297
- * Remove the view from the dom.
6298
- */
6299
- onModelDestroy: function () {
6300
- this.remove();
6301
- },
6302
-
6303
- /**
6304
- * Fade out the view and destroy the model
6305
- */
6306
- visualDestroyModel: function () {
6307
- this.builder.addHistoryEntry( 'row_deleted' );
6308
- var thisView = this;
6309
- this.$el.fadeOut( 'normal', function () {
6310
- thisView.model.destroy();
6311
- thisView.builder.model.refreshPanelsData();
6312
- } );
6313
- },
6314
-
6315
- onLabelChange: function( model, text ) {
6316
- if ( this.$('.so-row-label').length == 0 ) {
6317
- this.$( '.so-row-toolbar' ).prepend( '<h3 class="so-row-label">' + text + '</h3>' );
6318
- } else {
6319
- this.$('.so-row-label').text( text );
6320
- }
6321
- },
6322
-
6323
- /**
6324
- * Duplicate this row.
6325
- *
6326
- * @return {boolean}
6327
- */
6328
- duplicateHandler: function () {
6329
- this.builder.addHistoryEntry( 'row_duplicated' );
6330
-
6331
- var duplicateRow = this.model.clone( this.builder.model );
6332
-
6333
- this.builder.model.get('rows').add( duplicateRow, {
6334
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6335
- } );
6336
-
6337
- this.builder.model.refreshPanelsData();
6338
- },
6339
-
6340
- /**
6341
- * Copy the row to a localStorage
6342
- */
6343
- copyHandler: function(){
6344
- panels.helpers.clipboard.setModel( this.model );
6345
- },
6346
-
6347
- /**
6348
- * Create a new row and insert it
6349
- */
6350
- pasteHandler: function(){
6351
- var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
6352
-
6353
- if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
6354
- this.builder.addHistoryEntry( 'row_pasted' );
6355
- pastedModel.builder = this.builder.model;
6356
- this.builder.model.get('rows').add( pastedModel, {
6357
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6358
- } );
6359
- this.builder.model.refreshPanelsData();
6360
- }
6361
- },
6362
-
6363
- /**
6364
- * Handles deleting the row with a confirmation.
6365
- */
6366
- confirmedDeleteHandler: function ( e ) {
6367
- var $$ = $( e.target );
6368
-
6369
- // The user clicked on the dashicon
6370
- if ( $$.hasClass( 'dashicons' ) ) {
6371
- $$ = $.parent();
6372
- }
6373
-
6374
- if ( $$.hasClass( 'so-confirmed' ) ) {
6375
- this.visualDestroyModel();
6376
- } else {
6377
- var originalText = $$.html();
6378
-
6379
- $$.addClass( 'so-confirmed' ).html(
6380
- '<span class="dashicons dashicons-yes"></span>' + panelsOptions.loc.dropdown_confirm
6381
- );
6382
-
6383
- setTimeout( function () {
6384
- $$.removeClass( 'so-confirmed' ).html( originalText );
6385
- }, 2500 );
6386
- }
6387
- },
6388
-
6389
- /**
6390
- * Handle displaying the settings dialog
6391
- */
6392
- editSettingsHandler: function () {
6393
- if ( ! this.builder.supports( 'editRow' ) ) {
6394
- return;
6395
- }
6396
- // Lets open up an instance of the settings dialog
6397
- if ( this.dialog === null ) {
6398
- // Create the dialog
6399
- this.dialog = new panels.dialog.row();
6400
- this.dialog.setBuilder( this.builder ).setRowModel( this.model );
6401
- }
6402
-
6403
- this.dialog.openDialog();
6404
-
6405
- return this;
6406
- },
6407
-
6408
- /**
6409
- * Handle deleting this entire row.
6410
- */
6411
- deleteHandler: function () {
6412
- this.model.destroy();
6413
- return this;
6414
- },
6415
-
6416
- /**
6417
- * Change the row background color.
6418
- */
6419
- rowColorChangeHandler: function ( event ) {
6420
- this.$( '.so-row-color' ).removeClass( 'so-row-color-selected' );
6421
- var clickedColorElem = $( event.target );
6422
- var newColorLabel = clickedColorElem.data( 'color-label' );
6423
- var oldColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6424
- clickedColorElem.addClass( 'so-row-color-selected' );
6425
- this.$el.removeClass( 'so-row-color-' + oldColorLabel );
6426
- this.$el.addClass( 'so-row-color-' + newColorLabel );
6427
- this.model.set( 'color_label', newColorLabel );
6428
- },
6429
-
6430
- /**
6431
- * Handle a new cell being added to this row view. For now we'll assume the new cell is always last
6432
- */
6433
- handleCellAdd: function ( cell ) {
6434
- var cellView = new panels.view.cell( {
6435
- model: cell
6436
- } );
6437
- cellView.row = this;
6438
- cellView.render();
6439
- cellView.$el.appendTo( this.$( '.so-cells' ) );
6440
- },
6441
-
6442
- /**
6443
- * Handle a cell being removed from this row view
6444
- */
6445
- handleCellRemove: function ( cell ) {
6446
- // Find the view that ties in to the cell we're removing
6447
- this.$( '.so-cells > .cell' ).each( function () {
6448
- var view = $( this ).data( 'view' );
6449
- if ( _.isUndefined( view ) ) {
6450
- return;
6451
- }
6452
-
6453
- if ( view.model.cid === cell.cid ) {
6454
- // Remove this view
6455
- view.remove();
6456
- }
6457
- } );
6458
- },
6459
-
6460
- /**
6461
- * Build up the contextual menu for a row
6462
- *
6463
- * @param e
6464
- * @param menu
6465
- */
6466
- buildContextualMenu: function ( e, menu ) {
6467
- var options = [];
6468
- for ( var i = 1; i < 5; i ++ ) {
6469
- options.push( {
6470
- title: i + ' ' + panelsOptions.loc.contextual.column
6471
- } );
6472
- }
6473
-
6474
- if( this.builder.supports( 'addRow' ) ) {
6475
- menu.addSection(
6476
- 'add-row',
6477
- {
6478
- sectionTitle: panelsOptions.loc.contextual.add_row,
6479
- search: false
6480
- },
6481
- options,
6482
- function ( c ) {
6483
- this.builder.addHistoryEntry( 'row_added' );
6484
-
6485
- var columns = Number( c ) + 1;
6486
- var weights = [];
6487
- for ( var i = 0; i < columns; i ++ ) {
6488
- weights.push( {weight: 100 / columns } );
6489
- }
6490
-
6491
- // Create the actual row
6492
- var newRow = new panels.model.row( {
6493
- collection: this.collection
6494
- } );
6495
-
6496
- var cells = new panels.collection.cells(weights);
6497
- cells.each(function (cell) {
6498
- cell.row = newRow;
6499
- });
6500
- newRow.setCells(cells);
6501
- newRow.builder = this.builder.model;
6502
-
6503
- this.builder.model.get('rows').add( newRow, {
6504
- at: this.builder.model.get('rows').indexOf( this.model ) + 1
6505
- } );
6506
-
6507
- this.builder.model.refreshPanelsData();
6508
- }.bind( this )
6509
- );
6510
- }
6511
-
6512
- var actions = {};
6513
-
6514
- if( this.builder.supports( 'editRow' ) ) {
6515
- actions.edit = { title: panelsOptions.loc.contextual.row_edit };
6516
- }
6517
-
6518
- // Copy and paste functions
6519
- if ( panels.helpers.clipboard.canCopyPaste() ) {
6520
- actions.copy = { title: panelsOptions.loc.contextual.row_copy };
6521
- if ( this.builder.supports( 'addRow' ) && panels.helpers.clipboard.isModel( 'row-model' ) ) {
6522
- actions.paste = { title: panelsOptions.loc.contextual.row_paste };
6523
- }
6524
- }
6525
-
6526
- if( this.builder.supports( 'addRow' ) ) {
6527
- actions.duplicate = { title: panelsOptions.loc.contextual.row_duplicate };
6528
- }
6529
-
6530
- if( this.builder.supports( 'deleteRow' ) ) {
6531
- actions.delete = { title: panelsOptions.loc.contextual.row_delete, confirm: true };
6532
- }
6533
-
6534
- if( ! _.isEmpty( actions ) ) {
6535
- menu.addSection(
6536
- 'row-actions',
6537
- {
6538
- sectionTitle: panelsOptions.loc.contextual.row_actions,
6539
- search: false,
6540
- },
6541
- actions,
6542
- function ( c ) {
6543
- switch ( c ) {
6544
- case 'edit':
6545
- this.editSettingsHandler();
6546
- break;
6547
- case 'copy':
6548
- this.copyHandler();
6549
- break;
6550
- case 'paste':
6551
- this.pasteHandler();
6552
- break;
6553
- case 'duplicate':
6554
- this.duplicateHandler();
6555
- break;
6556
- case 'delete':
6557
- this.visualDestroyModel();
6558
- break;
6559
- }
6560
- }.bind( this )
6561
- );
6562
- }
6563
- },
6564
- } );
6565
 
6566
  },{}],28:[function(require,module,exports){
6567
  var panels = window.panels, $ = jQuery;
4820
  } );
4821
 
4822
  },{}],24:[function(require,module,exports){
4823
+ var panels = window.panels, $ = jQuery;
4824
+
4825
+ module.exports = Backbone.View.extend( {
4826
+ template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-cell' ).html() ) ),
4827
+ events: {
4828
+ 'click .cell-wrapper': 'handleCellClick'
4829
+ },
4830
+
4831
+ /* The row view that this cell is a part of */
4832
+ row: null,
4833
+ widgetSortable: null,
4834
+
4835
+ initialize: function () {
4836
+ this.model.get('widgets').on( 'add', this.onAddWidget, this );
4837
+ },
4838
+
4839
+ /**
4840
+ * Render the actual cell
4841
+ */
4842
+ render: function () {
4843
+ var templateArgs = {
4844
+ weight: this.model.get( 'weight' ),
4845
+ totalWeight: this.row.model.get('cells').totalWeight()
4846
+ };
4847
+
4848
+ this.setElement( this.template( templateArgs ) );
4849
+ this.$el.data( 'view', this );
4850
+
4851
+ // Now lets render any widgets that are currently in the row
4852
+ var thisView = this;
4853
+ this.model.get('widgets').each( function ( widget ) {
4854
+ var widgetView = new panels.view.widget( {model: widget} );
4855
+ widgetView.cell = thisView;
4856
+ widgetView.render();
4857
+
4858
+ widgetView.$el.appendTo( thisView.$( '.widgets-container' ) );
4859
+ } );
4860
+
4861
+ this.initSortable();
4862
+ this.initResizable();
4863
+
4864
+ return this;
4865
+ },
4866
+
4867
+ /**
4868
+ * Initialize the widget sortable
4869
+ */
4870
+ initSortable: function () {
4871
+ if( ! this.row.builder.supports( 'moveWidget' ) ) {
4872
+ return this;
4873
+ }
4874
+
4875
+ var cellView = this;
4876
+
4877
+ // Go up the view hierarchy until we find the ID attribute
4878
+ var builderID = cellView.row.builder.$el.attr( 'id' );
4879
+
4880
+ // Create a widget sortable that's connected with all other cells
4881
+ this.widgetSortable = this.$( '.widgets-container' ).sortable( {
4882
+ placeholder: "so-widget-sortable-highlight",
4883
+ connectWith: '#' + builderID + ' .so-cells .cell .widgets-container',
4884
+ tolerance: 'pointer',
4885
+ scroll: false,
4886
+ over: function ( e, ui ) {
4887
+ // This will make all the rows in the current builder resize
4888
+ cellView.row.builder.trigger( 'widget_sortable_move' );
4889
+ },
4890
+ stop: function ( e, ui ) {
4891
+ cellView.row.builder.addHistoryEntry( 'widget_moved' );
4892
+
4893
+ var $$ = $( ui.item ),
4894
+ widget = $$.data( 'view' ),
4895
+ targetCell = $$.closest( '.cell' ).data( 'view' );
4896
+
4897
+ // Move the model and the view to the new cell
4898
+ widget.model.moveToCell( targetCell.model, {}, $$.index() );
4899
+ widget.cell = targetCell;
4900
+
4901
+ widget.cell.row.builder.model.refreshPanelsData();
4902
+ },
4903
+ helper: function ( e, el ) {
4904
+ var helper = el.clone()
4905
+ .css( {
4906
+ 'width': el.outerWidth(),
4907
+ 'z-index': 10000,
4908
+ 'position': 'fixed'
4909
+ } )
4910
+ .addClass( 'widget-being-dragged' ).appendTo( 'body' );
4911
+
4912
+ // Center the helper to the mouse cursor.
4913
+ if ( el.outerWidth() > 720 ) {
4914
+ helper.animate( {
4915
+ 'margin-left': e.pageX - el.offset().left - (
4916
+ 480 / 2
4917
+ ),
4918
+ 'width': 480
4919
+ }, 'fast' );
4920
+ }
4921
+
4922
+ return helper;
4923
+ }
4924
+ } );
4925
+
4926
+ return this;
4927
+ },
4928
+
4929
+ /**
4930
+ * Refresh the widget sortable when a new widget is added
4931
+ */
4932
+ refreshSortable: function () {
4933
+ if ( ! _.isNull( this.widgetSortable ) ) {
4934
+ this.widgetSortable.sortable( 'refresh' );
4935
+ }
4936
+ },
4937
+
4938
+ /**
4939
+ * This will make the cell resizble
4940
+ */
4941
+ initResizable: function () {
4942
+ if( ! this.row.builder.supports( 'editRow' ) ) {
4943
+ return this;
4944
+ }
4945
+
4946
+ // var neighbor = this.$el.previous().data('view');
4947
+ var handle = this.$( '.resize-handle' ).css( 'position', 'absolute' );
4948
+ var container = this.row.$el;
4949
+ var cellView = this;
4950
+
4951
+ // The view of the cell to the left is stored when dragging starts.
4952
+ var previousCell;
4953
+
4954
+ handle.draggable( {
4955
+ axis: 'x',
4956
+ containment: container,
4957
+ start: function ( e, ui ) {
4958
+ // Set the containment to the cell parent
4959
+ previousCell = cellView.$el.prev().data( 'view' );
4960
+ if ( _.isUndefined( previousCell ) ) {
4961
+ return;
4962
+ }
4963
+
4964
+ // Create the clone for the current cell
4965
+ var newCellClone = cellView.$el.clone().appendTo( ui.helper ).css( {
4966
+ position: 'absolute',
4967
+ top: '0',
4968
+ width: cellView.$el.outerWidth(),
4969
+ left: 5,
4970
+ height: cellView.$el.outerHeight()
4971
+ } );
4972
+ newCellClone.find( '.resize-handle' ).remove();
4973
+
4974
+ // Create the clone for the previous cell
4975
+ var prevCellClone = previousCell.$el.clone().appendTo( ui.helper ).css( {
4976
+ position: 'absolute',
4977
+ top: '0',
4978
+ width: previousCell.$el.outerWidth(),
4979
+ right: 5,
4980
+ height: previousCell.$el.outerHeight()
4981
+ } );
4982
+ prevCellClone.find( '.resize-handle' ).remove();
4983
+
4984
+ $( this ).data( {
4985
+ 'newCellClone': newCellClone,
4986
+ 'prevCellClone': prevCellClone
4987
+ } );
4988
+ },
4989
+ drag: function ( e, ui ) {
4990
+ // Calculate the new cell and previous cell widths as a percent
4991
+ var containerWidth = cellView.row.$el.width() + 10;
4992
+ var ncw = cellView.model.get( 'weight' ) - (
4993
+ (
4994
+ ui.position.left + handle.outerWidth() / 2
4995
+ ) / containerWidth
4996
+ );
4997
+ var pcw = previousCell.model.get( 'weight' ) + (
4998
+ (
4999
+ ui.position.left + handle.outerWidth() / 2
5000
+ ) / containerWidth
5001
+ );
5002
+
5003
+ $( this ).data( 'newCellClone' ).css( 'width', containerWidth * ncw )
5004
+ .find( '.preview-cell-weight' ).html( Math.round( ncw * 1000 ) / 10 );
5005
+
5006
+ $( this ).data( 'prevCellClone' ).css( 'width', containerWidth * pcw )
5007
+ .find( '.preview-cell-weight' ).html( Math.round( pcw * 1000 ) / 10 );
5008
+ },
5009
+ stop: function ( e, ui ) {
5010
+ // Remove the clones
5011
+ $( this ).data( 'newCellClone' ).remove();
5012
+ $( this ).data( 'prevCellClone' ).remove();
5013
+
5014
+ var containerWidth = cellView.row.$el.width() + 10;
5015
+ var ncw = cellView.model.get( 'weight' ) - (
5016
+ (
5017
+ ui.position.left + handle.outerWidth() / 2
5018
+ ) / containerWidth
5019
+ );
5020
+ var pcw = previousCell.model.get( 'weight' ) + (
5021
+ (
5022
+ ui.position.left + handle.outerWidth() / 2
5023
+ ) / containerWidth
5024
+ );
5025
+
5026
+ if ( ncw > 0.02 && pcw > 0.02 ) {
5027
+ cellView.row.builder.addHistoryEntry( 'cell_resized' );
5028
+ cellView.model.set( 'weight', ncw );
5029
+ previousCell.model.set( 'weight', pcw );
5030
+ cellView.row.resize();
5031
+ }
5032
+
5033
+ ui.helper.css( 'left', - handle.outerWidth() / 2 );
5034
+
5035
+ // Refresh the panels data
5036
+ cellView.row.builder.model.refreshPanelsData();
5037
+ }
5038
+ } );
5039
+
5040
+ return this;
5041
+ },
5042
+
5043
+ /**
5044
+ * This is triggered when ever a widget is added to the row collection.
5045
+ *
5046
+ * @param widget
5047
+ */
5048
+ onAddWidget: function ( widget, collection, options ) {
5049
+ options = _.extend( {noAnimate: false}, options );
5050
+
5051
+ // Create the view for the widget
5052
+ var view = new panels.view.widget( {
5053
+ model: widget
5054
+ } );
5055
+ view.cell = this;
5056
+
5057
+ if ( _.isUndefined( widget.isDuplicate ) ) {
5058
+ widget.isDuplicate = false;
5059
+ }
5060
+
5061
+ // Render and load the form if this is a duplicate
5062
+ view.render( {
5063
+ 'loadForm': widget.isDuplicate
5064
+ } );
5065
+
5066
+ if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
5067
+ // Insert this at the end of the widgets container
5068
+ view.$el.appendTo( this.$( '.widgets-container' ) );
5069
+ } else {
5070
+ // We need to insert this at a specific position
5071
+ view.$el.insertAfter(
5072
+ this.$( '.widgets-container .so-widget' ).eq( options.at - 1 )
5073
+ );
5074
+ }
5075
+
5076
+ if ( options.noAnimate === false ) {
5077
+ // We need an animation
5078
+ view.visualCreate();
5079
+ }
5080
+
5081
+ this.refreshSortable();
5082
+ this.row.resize();
5083
+ },
5084
+
5085
+ /**
5086
+ * Handle this cell being clicked on
5087
+ *
5088
+ * @param e
5089
+ * @returns {boolean}
5090
+ */
5091
+ handleCellClick: function ( e ) {
5092
+ // Remove all existing selected cell indication for this builder
5093
+ this.row.builder.$el.find( '.so-cells .cell' ).removeClass( 'cell-selected' );
5094
+
5095
+ if( this.row.builder.activeCell === this && ! this.model.get('widgets').length ) {
5096
+ // This is a click on an empty cell
5097
+ this.row.builder.activeCell = null;
5098
+ }
5099
+ else {
5100
+ this.$el.addClass( 'cell-selected' );
5101
+ this.row.builder.activeCell = this;
5102
+ }
5103
+ },
5104
+
5105
+ /**
5106
+ * Insert a widget from the clipboard
5107
+ */
5108
+ pasteHandler: function(){
5109
+ var pastedModel = panels.helpers.clipboard.getModel( 'widget-model' );
5110
+ if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.widget ) {
5111
+ this.row.builder.addHistoryEntry( 'widget_pasted' );
5112
+ pastedModel.cell = this.model;
5113
+ this.model.get('widgets').add( pastedModel );
5114
+ this.row.builder.model.refreshPanelsData();
5115
+ }
5116
+ },
5117
+
5118
+ /**
5119
+ * Build up the contextual menu for a cell
5120
+ *
5121
+ * @param e
5122
+ * @param menu
5123
+ */
5124
+ buildContextualMenu: function ( e, menu ) {
5125
+ var thisView = this;
5126
+
5127
+ if( ! menu.hasSection( 'add-widget-below' ) ) {
5128
+ menu.addSection(
5129
+ 'add-widget-cell',
5130
+ {
5131
+ sectionTitle: panelsOptions.loc.contextual.add_widget_cell,
5132
+ searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
5133
+ defaultDisplay: panelsOptions.contextual.default_widgets
5134
+ },
5135
+ panelsOptions.widgets,
5136
+ function ( c ) {
5137
+ thisView.row.builder.addHistoryEntry( 'widget_added' );
5138
+
5139
+ var widget = new panels.model.widget( {
5140
+ class: c
5141
+ } );
5142
+
5143
+ // Add the widget to the cell model
5144
+ widget.cell = thisView.model;
5145
+ widget.cell.get('widgets').add( widget );
5146
+
5147
+ thisView.row.builder.model.refreshPanelsData();
5148
+ }
5149
+ );
5150
+ }
5151
+
5152
+ var actions = {};
5153
+ if ( this.row.builder.supports('addWidget') && panels.helpers.clipboard.isModel( 'widget-model' ) ) {
5154
+ actions.paste = {title: panelsOptions.loc.contextual.cell_paste_widget};
5155
+ }
5156
+
5157
+ if( ! _.isEmpty( actions ) ) {
5158
+ menu.addSection(
5159
+ 'cell-actions',
5160
+ {
5161
+ sectionTitle: panelsOptions.loc.contextual.cell_actions,
5162
+ search: false,
5163
+ },
5164
+ actions,
5165
+ function ( c ) {
5166
+ switch ( c ) {
5167
+ case 'paste':
5168
+ this.pasteHandler();
5169
+ break;
5170
+ }
5171
+
5172
+ this.row.builder.model.refreshPanelsData();
5173
+ }.bind( this )
5174
+ );
5175
+ }
5176
+
5177
+ // Add the contextual menu for the parent row
5178
+ this.row.buildContextualMenu( e, menu );
5179
+ }
5180
+ } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5181
 
5182
+ },{}],25:[function(require,module,exports){
5183
+ var panels = window.panels, $ = jQuery;
5184
+
5185
+ module.exports = Backbone.View.extend( {
5186
+ dialogTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog' ).html() ) ),
5187
+ dialogTabTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-tab' ).html() ) ),
5188
+
5189
+ tabbed: false,
5190
+ rendered: false,
5191
+ builder: false,
5192
+ className: 'so-panels-dialog-wrapper',
5193
+ dialogClass: '',
5194
+ dialogIcon: '',
5195
+ parentDialog: false,
5196
+ dialogOpen: false,
5197
+ editableLabel: false,
5198
+
5199
+ events: {
5200
+ 'click .so-close': 'closeDialog',
5201
+ 'click .so-nav.so-previous': 'navToPrevious',
5202
+ 'click .so-nav.so-next': 'navToNext',
5203
+ },
5204
+
5205
+ initialize: function () {
5206
+ // The first time this dialog is opened, render it
5207
+ this.once( 'open_dialog', this.render );
5208
+ this.once( 'open_dialog', this.attach );
5209
+ this.once( 'open_dialog', this.setDialogClass );
5210
+
5211
+ this.trigger( 'initialize_dialog', this );
5212
+
5213
+ if ( ! _.isUndefined( this.initializeDialog ) ) {
5214
+ this.initializeDialog();
5215
+ }
5216
+ },
5217
+
5218
+ /**
5219
+ * Returns the next dialog in the sequence. Should be overwritten by a child dialog.
5220
+ * @returns {null}
5221
+ */
5222
+ getNextDialog: function () {
5223
+ return null;
5224
+ },
5225
+
5226
+ /**
5227
+ * Returns the previous dialog in this sequence. Should be overwritten by child dialog.
5228
+ * @returns {null}
5229
+ */
5230
+ getPrevDialog: function () {
5231
+ return null;
5232
+ },
5233
+
5234
+ /**
5235
+ * Adds a dialog class to uniquely identify this dialog type
5236
+ */
5237
+ setDialogClass: function () {
5238
+ if ( this.dialogClass !== '' ) {
5239
+ this.$( '.so-panels-dialog' ).addClass( this.dialogClass );
5240
+ }
5241
+ },
5242
+
5243
+ /**
5244
+ * Set the builder that controls this dialog.
5245
+ * @param {panels.view.builder} builder
5246
+ */
5247
+ setBuilder: function ( builder ) {
5248
+ this.builder = builder;
5249
+
5250
+ // Trigger an add dialog event on the builder so it can modify the dialog in any way
5251
+ builder.trigger( 'add_dialog', this, this.builder );
5252
+
5253
+ return this;
5254
+ },
5255
+
5256
+ /**
5257
+ * Attach the dialog to the window
5258
+ */
5259
+ attach: function () {
5260
+ this.$el.appendTo( 'body' );
5261
+
5262
+ return this;
5263
+ },
5264
+
5265
+ /**
5266
+ * Converts an HTML representation of the dialog into arguments for a dialog box
5267
+ * @param html HTML for the dialog
5268
+ * @param args Arguments passed to the template
5269
+ * @returns {}
5270
+ */
5271
+ parseDialogContent: function ( html, args ) {
5272
+ // Add a CID
5273
+ args = _.extend( {cid: this.cid}, args );
5274
+
5275
+
5276
+ var c = $( (
5277
+ _.template( panels.helpers.utils.processTemplate( html ) )
5278
+ )( args ) );
5279
+ var r = {
5280
+ title: c.find( '.title' ).html(),
5281
+ buttons: c.find( '.buttons' ).html(),
5282
+ content: c.find( '.content' ).html()
5283
+ };
5284
+
5285
+ if ( c.has( '.left-sidebar' ) ) {
5286
+ r.left_sidebar = c.find( '.left-sidebar' ).html();
5287
+ }
5288
+
5289
+ if ( c.has( '.right-sidebar' ) ) {
5290
+ r.right_sidebar = c.find( '.right-sidebar' ).html();
5291
+ }
5292
+
5293
+ return r;
5294
+
5295
+ },
5296
+
5297
+ /**
5298
+ * Render the dialog and initialize the tabs
5299
+ *
5300
+ * @param attributes
5301
+ * @returns {panels.view.dialog}
5302
+ */
5303
+ renderDialog: function ( attributes ) {
5304
+ attributes = _.extend( {
5305
+ editableLabel: this.editableLabel,
5306
+ dialogIcon: this.dialogIcon,
5307
+ }, attributes );
5308
+
5309
+ this.$el.html( this.dialogTemplate( attributes ) ).hide();
5310
+ this.$el.data( 'view', this );
5311
+ this.$el.addClass( 'so-panels-dialog-wrapper' );
5312
+
5313
+ if ( this.parentDialog !== false ) {
5314
+ // Add a link to the parent dialog as a sort of crumbtrail.
5315
+ var thisDialog = this;
5316
+ var dialogParent = $( '<h3 class="so-parent-link"></h3>' ).html( this.parentDialog.text + '<div class="so-separator"></div>' );
5317
+ dialogParent.click( function ( e ) {
5318
+ e.preventDefault();
5319
+ thisDialog.closeDialog();
5320
+ thisDialog.parentDialog.openDialog();
5321
+ } );
5322
+ this.$( '.so-title-bar' ).prepend( dialogParent );
5323
+ }
5324
+
5325
+ if( this.$( '.so-title-bar .so-title-editable' ).length ) {
5326
+ // Added here because .so-edit-title is only available after the template has been rendered.
5327
+ this.initEditableLabel();
5328
+ }
5329
+
5330
+ return this;
5331
+ },
5332
+
5333
+ /**
5334
+ * Initialize the sidebar tabs
5335
+ */
5336
+ initTabs: function () {
5337
+ var tabs = this.$( '.so-sidebar-tabs li a' );
5338
+
5339
+ if ( tabs.length === 0 ) {
5340
+ return this;
5341
+ }
5342
+
5343
+ var thisDialog = this;
5344
+ tabs.click( function ( e ) {
5345
+ e.preventDefault();
5346
+ var $$ = $( this );
5347
+
5348
+ thisDialog.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
5349
+ thisDialog.$( '.so-content .so-content-tabs > *' ).hide();
5350
+
5351
+ $$.parent().addClass( 'tab-active' );
5352
+
5353
+ var url = $$.attr( 'href' );
5354
+ if ( ! _.isUndefined( url ) && url.charAt( 0 ) === '#' ) {
5355
+ // Display the new tab
5356
+ var tabName = url.split( '#' )[1];
5357
+ thisDialog.$( '.so-content .so-content-tabs .tab-' + tabName ).show();
5358
+ }
5359
+
5360
+ // This lets other dialogs implement their own custom handlers
5361
+ thisDialog.trigger( 'tab_click', $$ );
5362
+
5363
+ } );
5364
+
5365
+ // Trigger a click on the first tab
5366
+ this.$( '.so-sidebar-tabs li a' ).first().click();
5367
+ return this;
5368
+ },
5369
+
5370
+ initToolbar: function () {
5371
+ // Trigger simplified click event for elements marked as toolbar buttons.
5372
+ var buttons = this.$( '.so-toolbar .so-buttons .so-toolbar-button' );
5373
+ buttons.click( function ( e ) {
5374
+ e.preventDefault();
5375
+
5376
+ this.trigger( 'button_click', $( e.currentTarget ) );
5377
+ }.bind( this ) );
5378
+
5379
+ // Handle showing and hiding the dropdown list items
5380
+ var $dropdowns = this.$( '.so-toolbar .so-buttons .so-dropdown-button' );
5381
+ $dropdowns.click( function ( e ) {
5382
+ e.preventDefault();
5383
+ var $dropdownButton = $( e.currentTarget );
5384
+ var $dropdownList = $dropdownButton.siblings( '.so-dropdown-links-wrapper' );
5385
+ if ( $dropdownList.is( '.hidden' ) ) {
5386
+ $dropdownList.removeClass( 'hidden' );
5387
+ } else {
5388
+ $dropdownList.addClass( 'hidden' );
5389
+ }
5390
+
5391
+ }.bind( this ) );
5392
+
5393
+ // Hide dropdown list on click anywhere, unless it's a dropdown option which requires confirmation in it's
5394
+ // unconfirmed state.
5395
+ $( 'html' ).click( function ( e ) {
5396
+ this.$( '.so-dropdown-links-wrapper' ).not( '.hidden' ).each( function ( index, el ) {
5397
+ var $dropdownList = $( el );
5398
+ var $trgt = $( e.target );
5399
+ if ( $trgt.length === 0 || !(
5400
+ (
5401
+ $trgt.is('.so-needs-confirm') && !$trgt.is('.so-confirmed')
5402
+ ) || $trgt.is('.so-dropdown-button')
5403
+ ) ) {
5404
+ $dropdownList.addClass('hidden');
5405
+ }
5406
+ } );
5407
+ }.bind( this ) );
5408
+ },
5409
+
5410
+ /**
5411
+ * Initialize the editable dialog title
5412
+ */
5413
+ initEditableLabel: function(){
5414
+ var $editElt = this.$( '.so-title-bar .so-title-editable' );
5415
+
5416
+ $editElt.keypress( function ( event ) {
5417
+ var enterPressed = event.type === 'keypress' && event.keyCode === 13;
5418
+ if ( enterPressed ) {
5419
+ // Need to make sure tab focus is on another element, otherwise pressing enter multiple times refocuses
5420
+ // the element and allows newlines.
5421
+ var tabbables = $( ':tabbable' );
5422
+ var curTabIndex = tabbables.index( $editElt );
5423
+ tabbables.eq( curTabIndex + 1 ).focus();
5424
+ // After the above, we're somehow left with the first letter of text selected,
5425
+ // so this removes the selection.
5426
+ window.getSelection().removeAllRanges();
5427
+ }
5428
+ return !enterPressed;
5429
+ } ).blur( function () {
5430
+ var newValue = $editElt.text().replace( /^\s+|\s+$/gm, '' );
5431
+ var oldValue = $editElt.data( 'original-value' ).replace( /^\s+|\s+$/gm, '' );
5432
+ if ( newValue !== oldValue ) {
5433
+ $editElt.text( newValue );
5434
+ this.trigger( 'edit_label', newValue );
5435
+ }
5436
+
5437
+ }.bind( this ) );
5438
+
5439
+ $editElt.focus( function() {
5440
+ $editElt.data( 'original-value', $editElt.text() );
5441
+ panels.helpers.utils.selectElementContents( this );
5442
+ } );
5443
+ },
5444
+
5445
+ /**
5446
+ * Quickly setup the dialog by opening and closing it.
5447
+ */
5448
+ setupDialog: function () {
5449
+ this.openDialog();
5450
+ this.closeDialog();
5451
+ },
5452
+
5453
+ /**
5454
+ * Refresh the next and previous buttons.
5455
+ */
5456
+ refreshDialogNav: function () {
5457
+ this.$( '.so-title-bar .so-nav' ).show().removeClass( 'so-disabled' );
5458
+
5459
+ // Lets also hide the next and previous if we don't have a next and previous dialog
5460
+ var nextDialog = this.getNextDialog();
5461
+ var nextButton = this.$( '.so-title-bar .so-next' );
5462
+
5463
+ var prevDialog = this.getPrevDialog();
5464
+ var prevButton = this.$( '.so-title-bar .so-previous' );
5465
+
5466
+ if ( nextDialog === null ) {
5467
+ nextButton.hide();
5468
+ }
5469
+ else if ( nextDialog === false ) {
5470
+ nextButton.addClass( 'so-disabled' );
5471
+ }
5472
+
5473
+ if ( prevDialog === null ) {
5474
+ prevButton.hide();
5475
+ }
5476
+ else if ( prevDialog === false ) {
5477
+ prevButton.addClass( 'so-disabled' );
5478
+ }
5479
+ },
5480
+
5481
+ /**
5482
+ * Open the dialog
5483
+ */
5484
+ openDialog: function ( options ) {
5485
+ options = _.extend( {
5486
+ silent: false
5487
+ }, options );
5488
+
5489
+ if ( ! options.silent ) {
5490
+ this.trigger( 'open_dialog' );
5491
+ }
5492
+
5493
+ this.dialogOpen = true;
5494
+
5495
+ this.refreshDialogNav();
5496
+
5497
+ // Stop scrolling for the main body
5498
+ panels.helpers.pageScroll.lock();
5499
+
5500
+ // Start listen for keyboard keypresses.
5501
+ $( window ).on( 'keyup', this.keyboardListen );
5502
+
5503
+ this.$el.show();
5504
+
5505
+ if ( ! options.silent ) {
5506
+ // This triggers once everything is visible
5507
+ this.trigger( 'open_dialog_complete' );
5508
+ this.builder.trigger( 'open_dialog', this );
5509
+ $( document ).trigger( 'open_dialog', this );
5510
+ }
5511
+ },
5512
+
5513
+ /**
5514
+ * Close the dialog
5515
+ *
5516
+ * @param e
5517
+ * @returns {boolean}
5518
+ */
5519
+ closeDialog: function ( options ) {
5520
+ options = _.extend( {
5521
+ silent: false
5522
+ }, options );
5523
+
5524
+ if ( ! options.silent ) {
5525
+ this.trigger( 'close_dialog' );
5526
+ }
5527
+
5528
+ this.dialogOpen = false;
5529
+
5530
+ this.$el.hide();
5531
+ panels.helpers.pageScroll.unlock();
5532
+
5533
+ // Stop listen for keyboard keypresses.
5534
+ $( window ).off( 'keyup', this.keyboardListen );
5535
+
5536
+ if ( ! options.silent ) {
5537
+ // This triggers once everything is hidden
5538
+ this.trigger( 'close_dialog_complete' );
5539
+ this.builder.trigger( 'close_dialog', this );
5540
+ }
5541
+ },
5542
+
5543
+ /**
5544
+ * Keyboard events handler
5545
+ */
5546
+ keyboardListen: function ( e ) {
5547
+ // [Esc] to close
5548
+ if ( e.which === 27 ) {
5549
+ $( '.so-panels-dialog-wrapper .so-close' ).trigger( 'click' );
5550
+ }
5551
+ },
5552
+
5553
+ /**
5554
+ * Navigate to the previous dialog
5555
+ */
5556
+ navToPrevious: function () {
5557
+ this.closeDialog();
5558
+
5559
+ var prev = this.getPrevDialog();
5560
+ if ( prev !== null && prev !== false ) {
5561
+ prev.openDialog();
5562
+ }
5563
+ },
5564
+
5565
+ /**
5566
+ * Navigate to the next dialog
5567
+ */
5568
+ navToNext: function () {
5569
+ this.closeDialog();
5570
+
5571
+ var next = this.getNextDialog();
5572
+ if ( next !== null && next !== false ) {
5573
+ next.openDialog();
5574
+ }
5575
+ },
5576
+
5577
+ /**
5578
+ * Get the values from the form and convert them into a data array
5579
+ */
5580
+ getFormValues: function ( formSelector ) {
5581
+ if ( _.isUndefined( formSelector ) ) {
5582
+ formSelector = '.so-content';
5583
+ }
5584
+
5585
+ var $f = this.$( formSelector );
5586
+
5587
+ var data = {}, parts;
5588
+
5589
+ // Find all the named fields in the form
5590
+ $f.find( '[name]' ).each( function () {
5591
+ var $$ = $( this );
5592
+
5593
+ try {
5594
+
5595
+ var name = /([A-Za-z_]+)\[(.*)\]/.exec( $$.attr( 'name' ) );
5596
+ if ( _.isEmpty( name ) ) {
5597
+ return true;
5598
+ }
5599
+
5600
+ // Create an array with the parts of the name
5601
+ if ( _.isUndefined( name[2] ) ) {
5602
+ parts = $$.attr( 'name' );
5603
+ } else {
5604
+ parts = name[2].split( '][' );
5605
+ parts.unshift( name[1] );
5606
+ }
5607
+
5608
+ parts = parts.map( function ( e ) {
5609
+ if ( ! isNaN( parseFloat( e ) ) && isFinite( e ) ) {
5610
+ return parseInt( e );
5611
+ } else {
5612
+ return e;
5613
+ }
5614
+ } );
5615
+
5616
+ var sub = data;
5617
+ var fieldValue = null;
5618
+
5619
+ var fieldType = (
5620
+ _.isString( $$.attr( 'type' ) ) ? $$.attr( 'type' ).toLowerCase() : false
5621
+ );
5622
+
5623
+ // First we need to get the value from the field
5624
+ if ( fieldType === 'checkbox' ) {
5625
+ if ( $$.is( ':checked' ) ) {
5626
+ fieldValue = $$.val() !== '' ? $$.val() : true;
5627
+ } else {
5628
+ fieldValue = null;
5629
+ }
5630
+ }
5631
+ else if ( fieldType === 'radio' ) {
5632
+ if ( $$.is( ':checked' ) ) {
5633
+ fieldValue = $$.val();
5634
+ } else {
5635
+ //skip over unchecked radios
5636
+ return;
5637
+ }
5638
+ }
5639
+ else if ( $$.prop( 'tagName' ) === 'SELECT' ) {
5640
+ var selected = $$.find( 'option:selected' );
5641
+
5642
+ if ( selected.length === 1 ) {
5643
+ fieldValue = $$.find( 'option:selected' ).val();
5644
+ }
5645
+ else if ( selected.length > 1 ) {
5646
+ // This is a mutli-select field
5647
+ fieldValue = _.map( $$.find( 'option:selected' ), function ( n, i ) {
5648
+ return $( n ).val();
5649
+ } );
5650
+ }
5651
+
5652
+ } else {
5653
+ // This is a fallback that will work for most fields
5654
+ fieldValue = $$.val();
5655
+ }
5656
+
5657
+ // Now, we need to filter this value if necessary
5658
+ if ( ! _.isUndefined( $$.data( 'panels-filter' ) ) ) {
5659
+ switch ( $$.data( 'panels-filter' ) ) {
5660
+ case 'json_parse':
5661
+ // Attempt to parse the JSON value of this field
5662
+ try {
5663
+ fieldValue = JSON.parse( fieldValue );
5664
+ }
5665
+ catch ( err ) {
5666
+ fieldValue = '';
5667
+ }
5668
+ break;
5669
+ }
5670
+ }
5671
+
5672
+ // Now convert this into an array
5673
+ if ( fieldValue !== null ) {
5674
+ for ( var i = 0; i < parts.length; i ++ ) {
5675
+ if ( i === parts.length - 1 ) {
5676
+ if ( parts[i] === '' ) {
5677
+ // This needs to be an array
5678
+ sub.push( fieldValue );
5679
+ } else {
5680
+ sub[parts[i]] = fieldValue;
5681
+ }
5682
+ } else {
5683
+ if ( _.isUndefined( sub[parts[i]] ) ) {
5684
+ if ( parts[i + 1] === '' ) {
5685
+ sub[parts[i]] = [];
5686
+ } else {
5687
+ sub[parts[i]] = {};
5688
+ }
5689
+ }
5690
+ sub = sub[parts[i]];
5691
+ }
5692
+ }
5693
+ }
5694
+ }
5695
+ catch ( error ) {
5696
+ // Ignore this error, just log the message for debugging
5697
+ console.log( 'Field [' + $$.attr('name') + '] could not be processed and was skipped - ' + error.message );
5698
+ }
5699
+
5700
+ } ); // End of each through input fields
5701
+
5702
+ return data;
5703
+ },
5704
+
5705
+ /**
5706
+ * Set a status message for the dialog
5707
+ */
5708
+ setStatusMessage: function ( message, loading, error ) {
5709
+ var msg = error ? '<span class="dashicons dashicons-warning"></span>' + message : message;
5710
+ this.$( '.so-toolbar .so-status' ).html( msg );
5711
+ if ( ! _.isUndefined( loading ) && loading ) {
5712
+ this.$( '.so-toolbar .so-status' ).addClass( 'so-panels-loading' );
5713
+ } else {
5714
+ this.$( '.so-toolbar .so-status' ).removeClass( 'so-panels-loading' );
5715
+ }
5716
+ },
5717
+
5718
+ /**
5719
+ * Set the parent after.
5720
+ */
5721
+ setParent: function ( text, dialog ) {
5722
+ this.parentDialog = {
5723
+ text: text,
5724
+ dialog: dialog
5725
+ };
5726
+ }
5727
+ } );
5728
 
5729
  },{}],26:[function(require,module,exports){
5730
  var panels = window.panels, $ = jQuery;
6140
  } );
6141
 
6142
  },{}],27:[function(require,module,exports){
6143
+ var panels = window.panels, $ = jQuery;
6144
+
6145
+ module.exports = Backbone.View.extend( {
6146
+ template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-row' ).html() ) ),
6147
+
6148
+ events: {
6149
+ 'click .so-row-settings': 'editSettingsHandler',
6150
+ 'click .so-row-duplicate': 'duplicateHandler',
6151
+ 'click .so-row-delete': 'confirmedDeleteHandler',
6152
+ 'click .so-row-color': 'rowColorChangeHandler',
6153
+ },
6154
+
6155
+ builder: null,
6156
+ dialog: null,
6157
+
6158
+ /**
6159
+ * Initialize the row view
6160
+ */
6161
+ initialize: function () {
6162
+
6163
+ var rowCells = this.model.get('cells');
6164
+ rowCells.on( 'add', this.handleCellAdd, this );
6165
+ rowCells.on( 'remove', this.handleCellRemove, this );
6166
+ this.model.on( 'reweight_cells', this.resize, this );
6167
+
6168
+ this.model.on( 'destroy', this.onModelDestroy, this );
6169
+ this.model.on( 'visual_destroy', this.visualDestroyModel, this );
6170
+
6171
+ var thisView = this;
6172
+ rowCells.each( function ( cell ) {
6173
+ thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6174
+ } );
6175
+
6176
+ // When ever a new cell is added, listen to it for new widgets
6177
+ rowCells.on( 'add', function ( cell ) {
6178
+ thisView.listenTo( cell.get('widgets'), 'add', thisView.resize );
6179
+ }, this );
6180
+
6181
+ this.model.on( 'change:label', this.onLabelChange, this );
6182
+ },
6183
+
6184
+ /**
6185
+ * Render the row.
6186
+ *
6187
+ * @returns {panels.view.row}
6188
+ */
6189
+ render: function () {
6190
+ var rowColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6191
+ var rowLabel = this.model.has( 'label' ) ? this.model.get( 'label' ) : '';
6192
+ this.setElement( this.template( { rowColorLabel: rowColorLabel, rowLabel: rowLabel } ) );
6193
+ this.$el.data( 'view', this );
6194
+
6195
+ // Create views for the cells in this row
6196
+ var thisView = this;
6197
+ this.model.get('cells').each( function ( cell ) {
6198
+ var cellView = new panels.view.cell( {
6199
+ model: cell
6200
+ } );
6201
+ cellView.row = thisView;
6202
+ cellView.render();
6203
+ cellView.$el.appendTo( thisView.$( '.so-cells' ) );
6204
+ } );
6205
+
6206
+ // Remove any unsupported actions
6207
+ if( ! this.builder.supports( 'rowAction' ) ) {
6208
+ this.$('.so-row-toolbar .so-dropdown-wrapper' ).remove();
6209
+ this.$el.addClass('so-row-no-actions');
6210
+ }
6211
+ else {
6212
+ if( ! this.builder.supports( 'editRow' ) ) {
6213
+ this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-settings' ).parent().remove();
6214
+ this.$el.addClass('so-row-no-edit');
6215
+ }
6216
+ if( ! this.builder.supports( 'addRow' ) ) {
6217
+ this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate' ).parent().remove();
6218
+ this.$el.addClass('so-row-no-duplicate');
6219
+ }
6220
+ if( ! this.builder.supports( 'deleteRow' ) ) {
6221
+ this.$('.so-row-toolbar .so-dropdown-links-wrapper .so-row-delete' ).parent().remove();
6222
+ this.$el.addClass('so-row-no-delete');
6223
+ }
6224
+ }
6225
+ if( ! this.builder.supports( 'moveRow' ) ) {
6226
+ this.$('.so-row-toolbar .so-row-move' ).remove();
6227
+ this.$el.addClass('so-row-no-move');
6228
+ }
6229
+ if( !$.trim( this.$('.so-row-toolbar').html() ).length ) {
6230
+ this.$('.so-row-toolbar' ).remove();
6231
+ }
6232
+
6233
+ // Resize the rows when ever the widget sortable moves
6234
+ this.builder.on( 'widget_sortable_move', this.resize, this );
6235
+ this.builder.on( 'builder_resize', this.resize, this );
6236
+
6237
+ this.resize();
6238
+
6239
+ return this;
6240
+ },
6241
+
6242
+ /**
6243
+ * Give a visual indication of the creation of this row
6244
+ */
6245
+ visualCreate: function () {
6246
+ this.$el.hide().fadeIn( 'fast' );
6247
+ },
6248
+
6249
+ /**
6250
+ * Visually resize the row so that all cell heights are the same and the widths so that they balance to 100%
6251
+ *
6252
+ * @param e
6253
+ */
6254
+ resize: function ( e ) {
6255
+ // Don't resize this
6256
+ if ( ! this.$el.is( ':visible' ) ) {
6257
+ return;
6258
+ }
6259
+
6260
+ // Reset everything to have an automatic height
6261
+ this.$( '.so-cells .cell-wrapper' ).css( 'min-height', 0 );
6262
+ this.$( '.so-cells .resize-handle' ).css( 'height', 0 );
6263
+
6264
+ // We'll tie the values to the row view, to prevent issue with values going to different rows
6265
+ var height = 0;
6266
+ this.$( '.so-cells .cell' ).each( function () {
6267
+ height = Math.max(
6268
+ height,
6269
+ $( this ).height()
6270
+ );
6271
+
6272
+ $( this ).css(
6273
+ 'width',
6274
+ ( $( this ).data( 'view' ).model.get( 'weight' ) * 100) + "%"
6275
+ );
6276
+ } );
6277
+
6278
+ // Resize all the grids and cell wrappers
6279
+ this.$( '.so-cells .cell-wrapper' ).css( 'min-height', Math.max( height, 63 ) );
6280
+ this.$( '.so-cells .resize-handle' ).css( 'height', this.$( '.so-cells .cell-wrapper' ).outerHeight() );
6281
+ },
6282
+
6283
+ /**
6284
+ * Remove the view from the dom.
6285
+ */
6286
+ onModelDestroy: function () {
6287
+ this.remove();
6288
+ },
6289
+
6290
+ /**
6291
+ * Fade out the view and destroy the model
6292
+ */
6293
+ visualDestroyModel: function () {
6294
+ this.builder.addHistoryEntry( 'row_deleted' );
6295
+ var thisView = this;
6296
+ this.$el.fadeOut( 'normal', function () {
6297
+ thisView.model.destroy();
6298
+ thisView.builder.model.refreshPanelsData();
6299
+ } );
6300
+ },
6301
+
6302
+ onLabelChange: function( model, text ) {
6303
+ if ( this.$('.so-row-label').length == 0 ) {
6304
+ this.$( '.so-row-toolbar' ).prepend( '<h3 class="so-row-label">' + text + '</h3>' );
6305
+ } else {
6306
+ this.$('.so-row-label').text( text );
6307
+ }
6308
+ },
6309
+
6310
+ /**
6311
+ * Duplicate this row.
6312
+ *
6313
+ * @return {boolean}
6314
+ */
6315
+ duplicateHandler: function () {
6316
+ this.builder.addHistoryEntry( 'row_duplicated' );
6317
+
6318
+ var duplicateRow = this.model.clone( this.builder.model );
6319
+
6320
+ this.builder.model.get('rows').add( duplicateRow, {
6321
+ at: this.builder.model.get('rows').indexOf( this.model ) + 1
6322
+ } );
6323
+
6324
+ this.builder.model.refreshPanelsData();
6325
+ },
6326
+
6327
+ /**
6328
+ * Copy the row to a localStorage
6329
+ */
6330
+ copyHandler: function(){
6331
+ panels.helpers.clipboard.setModel( this.model );
6332
+ },
6333
+
6334
+ /**
6335
+ * Create a new row and insert it
6336
+ */
6337
+ pasteHandler: function(){
6338
+ var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
6339
+
6340
+ if( ! _.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
6341
+ this.builder.addHistoryEntry( 'row_pasted' );
6342
+ pastedModel.builder = this.builder.model;
6343
+ this.builder.model.get('rows').add( pastedModel, {
6344
+ at: this.builder.model.get('rows').indexOf( this.model ) + 1
6345
+ } );
6346
+ this.builder.model.refreshPanelsData();
6347
+ }
6348
+ },
6349
+
6350
+ /**
6351
+ * Handles deleting the row with a confirmation.
6352
+ */
6353
+ confirmedDeleteHandler: function ( e ) {
6354
+ var $$ = $( e.target );
6355
+
6356
+ // The user clicked on the dashicon
6357
+ if ( $$.hasClass( 'dashicons' ) ) {
6358
+ $$ = $.parent();
6359
+ }
6360
+
6361
+ if ( $$.hasClass( 'so-confirmed' ) ) {
6362
+ this.visualDestroyModel();
6363
+ } else {
6364
+ var originalText = $$.html();
6365
+
6366
+ $$.addClass( 'so-confirmed' ).html(
6367
+ '<span class="dashicons dashicons-yes"></span>' + panelsOptions.loc.dropdown_confirm
6368
+ );
6369
+
6370
+ setTimeout( function () {
6371
+ $$.removeClass( 'so-confirmed' ).html( originalText );
6372
+ }, 2500 );
6373
+ }
6374
+ },
6375
+
6376
+ /**
6377
+ * Handle displaying the settings dialog
6378
+ */
6379
+ editSettingsHandler: function () {
6380
+ if ( ! this.builder.supports( 'editRow' ) ) {
6381
+ return;
6382
+ }
6383
+ // Lets open up an instance of the settings dialog
6384
+ if ( this.dialog === null ) {
6385
+ // Create the dialog
6386
+ this.dialog = new panels.dialog.row();
6387
+ this.dialog.setBuilder( this.builder ).setRowModel( this.model );
6388
+ }
6389
+
6390
+ this.dialog.openDialog();
6391
+
6392
+ return this;
6393
+ },
6394
+
6395
+ /**
6396
+ * Handle deleting this entire row.
6397
+ */
6398
+ deleteHandler: function () {
6399
+ this.model.destroy();
6400
+ return this;
6401
+ },
6402
+
6403
+ /**
6404
+ * Change the row background color.
6405
+ */
6406
+ rowColorChangeHandler: function ( event ) {
6407
+ this.$( '.so-row-color' ).removeClass( 'so-row-color-selected' );
6408
+ var clickedColorElem = $( event.target );
6409
+ var newColorLabel = clickedColorElem.data( 'color-label' );
6410
+ var oldColorLabel = this.model.has( 'color_label' ) ? this.model.get( 'color_label' ) : 1;
6411
+ clickedColorElem.addClass( 'so-row-color-selected' );
6412
+ this.$el.removeClass( 'so-row-color-' + oldColorLabel );
6413
+ this.$el.addClass( 'so-row-color-' + newColorLabel );
6414
+ this.model.set( 'color_label', newColorLabel );
6415
+ },
6416
+
6417
+ /**
6418
+ * Handle a new cell being added to this row view. For now we'll assume the new cell is always last
6419
+ */
6420
+ handleCellAdd: function ( cell ) {
6421
+ var cellView = new panels.view.cell( {
6422
+ model: cell
6423
+ } );
6424
+ cellView.row = this;
6425
+ cellView.render();
6426
+ cellView.$el.appendTo( this.$( '.so-cells' ) );
6427
+ },
6428
+
6429
+ /**
6430
+ * Handle a cell being removed from this row view
6431
+ */
6432
+ handleCellRemove: function ( cell ) {
6433
+ // Find the view that ties in to the cell we're removing
6434
+ this.$( '.so-cells > .cell' ).each( function () {
6435
+ var view = $( this ).data( 'view' );
6436
+ if ( _.isUndefined( view ) ) {
6437
+ return;
6438
+ }
6439
+
6440
+ if ( view.model.cid === cell.cid ) {
6441
+ // Remove this view
6442
+ view.remove();
6443
+ }
6444
+ } );
6445
+ },
6446
+
6447
+ /**
6448
+ * Build up the contextual menu for a row
6449
+ *
6450
+ * @param e
6451
+ * @param menu
6452
+ */
6453
+ buildContextualMenu: function ( e, menu ) {
6454
+ var options = [];
6455
+ for ( var i = 1; i < 5; i ++ ) {
6456
+ options.push( {
6457
+ title: i + ' ' + panelsOptions.loc.contextual.column
6458
+ } );
6459
+ }
6460
+
6461
+ if( this.builder.supports( 'addRow' ) ) {
6462
+ menu.addSection(
6463
+ 'add-row',
6464
+ {
6465
+ sectionTitle: panelsOptions.loc.contextual.add_row,
6466
+ search: false
6467
+ },
6468
+ options,
6469
+ function ( c ) {
6470
+ this.builder.addHistoryEntry( 'row_added' );
6471
+
6472
+ var columns = Number( c ) + 1;
6473
+ var weights = [];
6474
+ for ( var i = 0; i < columns; i ++ ) {
6475
+ weights.push( {weight: 100 / columns } );
6476
+ }
6477
+
6478
+ // Create the actual row
6479
+ var newRow = new panels.model.row( {
6480
+ collection: this.collection
6481
+ } );
6482
+
6483
+ var cells = new panels.collection.cells(weights);
6484
+ cells.each(function (cell) {
6485
+ cell.row = newRow;
6486
+ });
6487
+ newRow.setCells(cells);
6488
+ newRow.builder = this.builder.model;
6489
+
6490
+ this.builder.model.get('rows').add( newRow, {
6491
+ at: this.builder.model.get('rows').indexOf( this.model ) + 1
6492
+ } );
6493
+
6494
+ this.builder.model.refreshPanelsData();
6495
+ }.bind( this )
6496
+ );
6497
+ }
6498
+
6499
+ var actions = {};
6500
+
6501
+ if( this.builder.supports( 'editRow' ) ) {
6502
+ actions.edit = { title: panelsOptions.loc.contextual.row_edit };
6503
+ }
6504
+
6505
+ // Copy and paste functions
6506
+ if ( panels.helpers.clipboard.canCopyPaste() ) {
6507
+ actions.copy = { title: panelsOptions.loc.contextual.row_copy };
6508
+ if ( this.builder.supports( 'addRow' ) && panels.helpers.clipboard.isModel( 'row-model' ) ) {
6509
+ actions.paste = { title: panelsOptions.loc.contextual.row_paste };
6510
+ }
6511
+ }
6512
+
6513
+ if( this.builder.supports( 'addRow' ) ) {
6514
+ actions.duplicate = { title: panelsOptions.loc.contextual.row_duplicate };
6515
+ }
6516
+
6517
+ if( this.builder.supports( 'deleteRow' ) ) {
6518
+ actions.delete = { title: panelsOptions.loc.contextual.row_delete, confirm: true };
6519
+ }
6520
+
6521
+ if( ! _.isEmpty( actions ) ) {
6522
+ menu.addSection(
6523
+ 'row-actions',
6524
+ {
6525
+ sectionTitle: panelsOptions.loc.contextual.row_actions,
6526
+ search: false,
6527
+ },
6528
+ actions,
6529
+ function ( c ) {
6530
+ switch ( c ) {
6531
+ case 'edit':
6532
+ this.editSettingsHandler();
6533
+ break;
6534
+ case 'copy':
6535
+ this.copyHandler();
6536
+ break;
6537
+ case 'paste':
6538
+ this.pasteHandler();
6539
+ break;
6540
+ case 'duplicate':
6541
+ this.duplicateHandler();
6542
+ break;
6543
+ case 'delete':
6544
+ this.visualDestroyModel();
6545
+ break;
6546
+ }
6547
+ }.bind( this )
6548
+ );
6549
+ }
6550
+ },
6551
+ } );
6552
 
6553
  },{}],28:[function(require,module,exports){
6554
  var panels = window.panels, $ = jQuery;
js/{siteorigin-panels-262.min.js → siteorigin-panels-263.min.js} RENAMED
@@ -1,4 +1,4 @@
1
  !function e(t,i,s){function l(n,a){if(!i[n]){if(!t[n]){var r="function"==typeof require&&require;if(!a&&r)return r(n,!0);if(o)return o(n,!0);var d=new Error("Cannot find module '"+n+"'");throw d.code="MODULE_NOT_FOUND",d}var c=i[n]={exports:{}};t[n][0].call(c.exports,function(e){var i=t[n][1][e];return l(i||e)},c,c.exports,e,t,i,s)}return i[n].exports}for(var o="function"==typeof require&&require,n=0;n<s.length;n++)l(s[n]);return l}({1:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.cell,initialize:function(){},totalWeight:function(){var e=0;return this.each(function(t){e+=t.get("weight")}),e}})},{}],2:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.historyEntry,builder:null,maxSize:12,initialize:function(){this.on("add",this.onAddEntry,this)},addEntry:function(e,t){_.isEmpty(t)&&(t=this.builder.getPanelsData());var i=new s.model.historyEntry({text:e,data:JSON.stringify(t),time:parseInt((new Date).getTime()/1e3),collection:this});this.add(i)},onAddEntry:function(e){if(this.models.length>1){var t=this.at(this.models.length-2);(e.get("text")===t.get("text")&&e.get("time")-t.get("time")<15||e.get("data")===t.get("data"))&&(this.remove(e),t.set("count",t.get("count")+1))}for(;this.models.length>this.maxSize;)this.shift()}})},{}],3:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.row,empty:function(){for(var e;;){if(!(e=this.collection.first()))break;e.destroy()}}})},{}],4:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.widget,initialize:function(){}})},{}],5:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({dialogClass:"so-panels-dialog-add-builder",render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-builder").html(),{})),this.$(".so-content .siteorigin-panels-builder").append(this.builder.$el)},initializeDialog:function(){var e=this;this.once("open_dialog_complete",function(){e.builder.initSortable()}),this.on("open_dialog_complete",function(){e.builder.trigger("builder_resize")})}})},{}],6:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({historyEntryTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-history-entry").html())),entries:{},currentEntry:null,revertEntry:null,selectedEntry:null,previewScrollTop:null,dialogClass:"so-panels-dialog-history",dialogIcon:"history",events:{"click .so-close":"closeDialog","click .so-restore":"restoreSelectedEntry"},initializeDialog:function(){this.entries=new s.collection.historyEntries,this.on("open_dialog",this.setCurrentEntry,this),this.on("open_dialog",this.renderHistoryEntries,this)},render:function(){var e=this;this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-history").html(),{})),this.$("iframe.siteorigin-panels-history-iframe").load(function(){var t=l(this);t.show(),t.contents().scrollTop(e.previewScrollTop)})},setRevertEntry:function(e){this.revertEntry=new s.model.historyEntry({data:JSON.stringify(e.getPanelsData()),time:parseInt((new Date).getTime()/1e3)})},setCurrentEntry:function(){this.currentEntry=new s.model.historyEntry({data:JSON.stringify(this.builder.model.getPanelsData()),time:parseInt((new Date).getTime()/1e3)}),this.selectedEntry=this.currentEntry,this.previewEntry(this.currentEntry),this.$(".so-buttons .so-restore").addClass("disabled")},renderHistoryEntries:function(){var e=this,t=this.$(".history-entries").empty();this.currentEntry.get("data")===this.revertEntry.get("data")&&_.isEmpty(this.entries.models)||l(this.historyEntryTemplate({title:panelsOptions.loc.history.revert,count:1})).data("historyEntry",this.revertEntry).prependTo(t),this.entries.each(function(i){var s=e.historyEntryTemplate({title:panelsOptions.loc.history[i.get("text")],count:i.get("count")});l(s).data("historyEntry",i).prependTo(t)}),l(this.historyEntryTemplate({title:panelsOptions.loc.history.current,count:1})).data("historyEntry",this.currentEntry).addClass("so-selected").prependTo(t),t.find(".history-entry").click(function(){var i=jQuery(this);t.find(".history-entry").not(i).removeClass("so-selected"),i.addClass("so-selected");var s=i.data("historyEntry");e.selectedEntry=s,e.selectedEntry.cid!==e.currentEntry.cid?e.$(".so-buttons .so-restore").removeClass("disabled"):e.$(".so-buttons .so-restore").addClass("disabled"),e.previewEntry(s)}),this.updateEntryTimes()},previewEntry:function(e){var t=this.$("iframe.siteorigin-panels-history-iframe");t.hide(),this.previewScrollTop=t.contents().scrollTop(),this.$('form.history-form input[name="live_editor_panels_data"]').val(e.get("data")),this.$('form.history-form input[name="live_editor_post_ID"]').val(this.builder.config.postId),this.$("form.history-form").submit()},restoreSelectedEntry:function(){return!this.$(".so-buttons .so-restore").hasClass("disabled")&&(this.currentEntry.get("data")===this.selectedEntry.get("data")?(this.closeDialog(),!1):("restore"!==this.selectedEntry.get("text")&&this.builder.addHistoryEntry("restore",this.builder.model.getPanelsData()),this.builder.model.loadPanelsData(JSON.parse(this.selectedEntry.get("data"))),this.closeDialog(),!1))},updateEntryTimes:function(){var e=this;this.$(".history-entries .history-entry").each(function(){var t=jQuery(this),i=t.find(".timesince"),s=t.data("historyEntry");i.html(e.timeSince(s.get("time")))})},timeSince:function(e){var t,i=parseInt((new Date).getTime()/1e3)-e,s=[];return i>3600&&(t=Math.floor(i/3600),1===t?s.push(panelsOptions.loc.time.hour.replace("%d",t)):s.push(panelsOptions.loc.time.hours.replace("%d",t)),i-=3600*t),i>60&&(t=Math.floor(i/60),1===t?s.push(panelsOptions.loc.time.minute.replace("%d",t)):s.push(panelsOptions.loc.time.minutes.replace("%d",t)),i-=60*t),i>0&&(1===i?s.push(panelsOptions.loc.time.second.replace("%d",i)):s.push(panelsOptions.loc.time.seconds.replace("%d",i))),_.isEmpty(s)?panelsOptions.loc.time.now:panelsOptions.loc.time.ago.replace("%s",s.slice(0,2).join(", "))}})},{}],7:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({directoryTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-directory-items").html())),builder:null,dialogClass:"so-panels-dialog-prebuilt-layouts",dialogIcon:"layouts",layoutCache:{},currentTab:!1,directoryPage:1,events:{"click .so-close":"closeDialog","click .so-sidebar-tabs li a":"tabClickHandler","click .so-content .layout":"layoutClickHandler","keyup .so-sidebar-search":"searchHandler","click .so-screenshot, .so-title":"directoryItemClickHandler"},initializeDialog:function(){var e=this;this.on("open_dialog",function(){e.$(".so-sidebar-tabs li a").first().click(),e.$(".so-status").removeClass("so-panels-loading")}),this.on("button_click",this.toolbarButtonClick,this)},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-prebuilt").html(),{})),this.initToolbar()},tabClickHandler:function(e){e.preventDefault(),this.selectedLayoutItem=null,this.uploadedLayout=null,this.updateButtonState(!1),this.$(".so-sidebar-tabs li").removeClass("tab-active");var t=l(e.target),i=t.attr("href").split("#")[1];t.parent().addClass("tab-active");var s=this;this.$(".so-content").empty(),s.currentTab=i,"import"==i?this.displayImportExport():this.displayLayoutDirectory("",1,i),s.$(".so-sidebar-search").val("")},displayImportExport:function(){var e=this.$(".so-content").empty().removeClass("so-panels-loading");e.html(l("#siteorigin-panels-dialog-prebuilt-importexport").html());var t=this,i=t.$(".import-upload-ui").hide();new plupload.Uploader({runtimes:"html5,silverlight,flash,html4",browse_button:i.find(".file-browse-button").get(0),container:i.get(0),drop_element:i.find(".drag-upload-area").get(0),file_data_name:"panels_import_data",multiple_queues:!1,max_file_size:panelsOptions.plupload.max_file_size,url:panelsOptions.plupload.url,flash_swf_url:panelsOptions.plupload.flash_swf_url,silverlight_xap_url:panelsOptions.plupload.silverlight_xap_url,filters:[{title:panelsOptions.plupload.filter_title,extensions:"json"}],multipart_params:{action:"so_panels_import_layout"},init:{PostInit:function(e){e.features.dragdrop&&i.addClass("has-drag-drop"),i.show().find(".progress-precent").css("width","0%")},FilesAdded:function(e){i.find(".file-browse-button").blur(),i.find(".drag-upload-area").removeClass("file-dragover"),i.find(".progress-bar").fadeIn("fast"),t.$(".js-so-selected-file").text(panelsOptions.loc.prebuilt_loading),e.start()},UploadProgress:function(e,t){i.find(".progress-precent").css("width",t.percent+"%")},FileUploaded:function(e,s,l){var o=JSON.parse(l.response);_.isUndefined(o.widgets)?alert(panelsOptions.plupload.error_message):(t.uploadedLayout=o,i.find(".progress-bar").hide(),t.$(".js-so-selected-file").text(panelsOptions.loc.ready_to_insert.replace("%s",s.name)),t.updateButtonState(!0))},Error:function(){alert(panelsOptions.plupload.error_message)}}}).init(),i.find(".drag-upload-area").on("dragover",function(){l(this).addClass("file-dragover")}).on("dragleave",function(){l(this).removeClass("file-dragover")}),e.find(".so-export").submit(function(e){var i=l(this),s=t.builder.model.getPanelsData(),o=l('input[name="post_title"]').val();o||(o=l('input[name="post_ID"]').val()),s.name=o,i.find('input[name="panels_export_data"]').val(JSON.stringify(s))})},displayLayoutDirectory:function(e,t,i){var s=this,o=this.$(".so-content").empty().addClass("so-panels-loading");if(void 0===e&&(e=""),void 0===t&&(t=1),void 0===i&&(i="directory-siteorigin"),i.match("^directory-")&&!panelsOptions.directory_enabled)return o.removeClass("so-panels-loading").html(l("#siteorigin-panels-directory-enable").html()),void o.find(".so-panels-enable-directory").click(function(n){n.preventDefault(),l.get(panelsOptions.ajaxurl,{action:"so_panels_directory_enable"},function(){}),panelsOptions.directory_enabled=!0,o.addClass("so-panels-loading"),s.displayLayoutDirectory(e,t,i)});l.get(panelsOptions.ajaxurl,{action:"so_panels_layouts_query",search:e,page:t,type:i},function(n){if(s.currentTab===i){o.removeClass("so-panels-loading").html(s.directoryTemplate(n));var a=o.find(".so-previous"),r=o.find(".so-next");t<=1?a.addClass("button-disabled"):a.click(function(i){i.preventDefault(),s.displayLayoutDirectory(e,t-1,s.currentTab)}),t===n.max_num_pages||0===n.max_num_pages?r.addClass("button-disabled"):r.click(function(i){i.preventDefault(),s.displayLayoutDirectory(e,t+1,s.currentTab)}),o.find(".so-screenshot").each(function(){var e=l(this),t=e.find(".so-screenshot-wrapper");if(t.css("height",t.width()/4*3+"px").addClass("so-loading"),""!==e.data("src"))var i=l("<img/>").attr("src",e.data("src")).load(function(){t.removeClass("so-loading").css("height","auto"),i.appendTo(t).hide().fadeIn("fast")});else l("<img/>").attr("src",panelsOptions.prebuiltDefaultScreenshot).appendTo(t).hide().fadeIn("fast")}),o.find(".so-directory-browse").html(n.title)}},"json")},directoryItemClickHandler:function(e){var t=this.$(e.target).closest(".so-directory-item");this.$(".so-directory-items").find(".selected").removeClass("selected"),t.addClass("selected"),this.selectedLayoutItem={lid:t.data("layout-id"),type:t.data("layout-type")},this.updateButtonState(!0)},toolbarButtonClick:function(e){if(!this.canAddLayout())return!1;var t=e.data("value");if(_.isUndefined(t))return!1;if(this.updateButtonState(!1),e.hasClass("so-needs-confirm")&&!e.hasClass("so-confirmed")){if(this.updateButtonState(!0),e.hasClass("so-confirming"))return;e.addClass("so-confirming");var i=e.html();return e.html('<span class="dashicons dashicons-yes"></span>'+e.data("confirm")),setTimeout(function(){e.removeClass("so-confirmed").html(i)},2500),setTimeout(function(){e.removeClass("so-confirming"),e.addClass("so-confirmed")},200),!1}this.addingLayout=!0,"import"===this.currentTab?this.addLayoutToBuilder(this.uploadedLayout,t):this.loadSelectedLayout().then(function(e){this.addLayoutToBuilder(e,t)}.bind(this))},canAddLayout:function(){return(this.selectedLayoutItem||this.uploadedLayout)&&!this.addingLayout},loadSelectedLayout:function(){this.setStatusMessage(panelsOptions.loc.prebuilt_loading,!0);var e=_.extend(this.selectedLayoutItem,{action:"so_panels_get_layout"}),t=new l.Deferred;return l.get(panelsOptions.ajaxurl,e,function(e){var i="";e.success?t.resolve(e.data):(i=e.data.message,t.reject(e.data)),this.setStatusMessage(i,!1,!e.success),this.updateButtonState(!0)}.bind(this)),t.promise()},searchHandler:function(e){13===e.keyCode&&this.displayLayoutDirectory(l(e.currentTarget).val(),1,this.currentTab)},updateButtonState:function(e){e=e&&(this.selectedLayoutItem||this.uploadedLayout);var t=this.$(".so-import-layout");t.prop("disabled",!e),e?t.removeClass("disabled"):t.addClass("disabled")},addLayoutToBuilder:function(e,t){this.builder.addHistoryEntry("prebuilt_loaded"),this.builder.model.loadPanelsData(e,t),this.addingLayout=!1,this.closeDialog()}})},{}],8:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({cellPreviewTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-row-cell-preview").html())),editableLabel:!0,events:{"click .so-close":"closeDialog","click .so-toolbar .so-save":"saveHandler","click .so-toolbar .so-insert":"insertHandler","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler","change .row-set-form > *":"setCellsFromForm","click .row-set-form button.set-row":"setCellsFromForm"},dialogIcon:"add-row",dialogClass:"so-panels-dialog-row-edit",styleType:"row",dialogType:"edit",row:{cells:null,style:{}},cellStylesCache:[],initializeDialog:function(){this.on("open_dialog",function(){_.isUndefined(this.model)||_.isEmpty(this.model.get("cells"))?this.setRowModel(null):this.setRowModel(this.model),this.regenerateRowPreview()},this),this.row={cells:new s.collection.cells([{weight:.5},{weight:.5}]),style:{}},this.dialogFormsLoaded=0;var e=this;this.on("form_loaded styles_loaded",function(){2===++this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("close_dialog",this.closeHandler),this.on("edit_label",function(e){if(e!==panelsOptions.loc.row.add&&e!==panelsOptions.loc.row.edit||(e=""),this.model.set("label",e),_.isEmpty(e)){var t="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.$(".so-title").text(t)}}.bind(this))},setRowDialogType:function(e){this.dialogType=e},render:function(){var e="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-row").html(),{title:e,dialogType:this.dialogType}));var t=this.$(".so-title");this.model.has("label")&&!_.isEmpty(this.model.get("label"))&&t.text(this.model.get("label")),this.$(".so-edit-title").val(t.text()),this.styles=new s.view.styles,this.styles.model=this.model,this.styles.render("row",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this}),this.builder.supports("addRow")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteRow")||this.$(".so-buttons .so-delete").remove();var i=this.$(".so-sidebar.so-right-sidebar");return this.styles.attach(i),this.styles.on("styles_loaded",function(e){e?i.removeClass("so-panels-loading"):(i.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),i.remove())},this),i.addClass("so-panels-loading"),_.isUndefined(this.model)||(this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction"))),this.$("input.so-row-field").keyup(function(){l(this).trigger("change")}),this},setRowModel:function(e){return this.model=e,_.isEmpty(this.model)?this:(this.row={cells:this.model.get("cells").clone(),style:{},ratio:this.model.get("ratio"),ratio_direction:this.model.get("ratio_direction")},this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction")),this.clearCellStylesCache(),this)},regenerateRowPreview:function(){var e=this,t=this.$(".row-preview"),i=this.getSelectedCellIndex();t.empty();var s;this.row.cells.each(function(o,n){var a=l(this.cellPreviewTemplate({weight:o.get("weight")}));t.append(a),n==i&&a.find(".preview-cell-in").addClass("cell-selected");var r,d=a.prev();d.length&&(r=l('<div class="resize-handle"></div>'),r.appendTo(a).dblclick(function(){var t=e.row.cells.at(n-1),i=o.get("weight")+t.get("weight");o.set("weight",i/2),t.set("weight",i/2),e.scaleRowWidths()}),r.draggable({axis:"x",containment:t,start:function(e,t){var i=a.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:a.outerWidth(),left:6,height:a.outerHeight()});i.find(".resize-handle").remove();var s=d.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:d.outerWidth(),right:6,height:d.outerHeight()});s.find(".resize-handle").remove(),l(this).data({newCellClone:i,prevCellClone:s}),a.find("> .preview-cell-in").css("visibility","hidden"),d.find("> .preview-cell-in").css("visibility","hidden")},drag:function(i,s){var o=e.row.cells.at(n).get("weight"),a=e.row.cells.at(n-1).get("weight"),r=o-(s.position.left+6)/t.width(),d=a+(s.position.left+6)/t.width();s.helper.offset().left,t.offset().left;l(this).data("newCellClone").css("width",t.width()*r).find(".preview-cell-weight").html(Math.round(1e3*r)/10),l(this).data("prevCellClone").css("width",t.width()*d).find(".preview-cell-weight").html(Math.round(1e3*d)/10)},stop:function(i,s){l(this).data("newCellClone").remove(),l(this).data("prevCellClone").remove(),a.find(".preview-cell-in").css("visibility","visible"),d.find(".preview-cell-in").css("visibility","visible");var o=s.position.left+6,r=o/t.width(),c=e.row.cells.at(n),h=e.row.cells.at(n-1);c.get("weight")-r>.02&&h.get("weight")+r>.02&&(c.set("weight",c.get("weight")-r),h.set("weight",h.get("weight")+r)),e.scaleRowWidths(),s.helper.css("left",-6)}})),a.click(function(e){if(l(e.target).is(".preview-cell")||l(e.target).is(".preview-cell-in")){var t=l(e.target);t.closest(".row-preview").find(".preview-cell .preview-cell-in").removeClass("cell-selected"),t.addClass("cell-selected"),this.openSelectedCellStyles()}}.bind(this)),a.find(".preview-cell-weight").click(function(i){e.$(".resize-handle").css("pointer-event","none").draggable("disable"),t.find(".preview-cell-weight").each(function(){var i=jQuery(this).hide();l('<input type="text" class="preview-cell-weight-input no-user-interacted" />').val(parseFloat(i.html())).insertAfter(i).focus(function(){clearTimeout(s)}).keyup(function(e){9!==e.keyCode&&l(this).removeClass("no-user-interacted"),13===e.keyCode&&(e.preventDefault(),l(this).blur())}).keydown(function(e){if(9===e.keyCode){e.preventDefault();var i=t.find(".preview-cell-weight-input"),s=i.index(l(this));s===i.length-1?i.eq(0).focus().select():i.eq(s+1).focus().select()}}).blur(function(){t.find(".preview-cell-weight-input").each(function(t,i){isNaN(parseFloat(l(i).val()))&&l(i).val(Math.floor(1e3*e.row.cells.at(t).get("weight"))/10)}),s=setTimeout(function(){if(0===t.find(".preview-cell-weight-input").length)return!1;var i=[],s=[],o=0,n=0;if(t.find(".preview-cell-weight-input").each(function(t,a){var r=parseFloat(l(a).val());r=isNaN(r)?1/e.row.cells.length:Math.round(10*r)/1e3;var d=!l(a).hasClass("no-user-interacted");i.push(r),s.push(d),d?o+=r:n+=r}),o>0&&n>0&&1-o>0)for(var a=0;a<i.length;a++)s[a]||(i[a]=i[a]/n*(1-o));var r=_.reduce(i,function(e,t){return e+t});i=i.map(function(e){return e/r}),Math.min.apply(Math,i)>.01&&e.row.cells.each(function(e,t){e.set("weight",i[t])}),t.find(".preview-cell").each(function(t,i){var s=e.row.cells.at(t).get("weight");l(i).animate({width:Math.round(1e3*s)/10+"%"},250),l(i).find(".preview-cell-weight-input").val(Math.round(1e3*s)/10)}),t.find(".preview-cell").css("overflow","visible"),setTimeout(function(){e.regenerateRowPreview()},260)},100)}).click(function(){l(this).select()})}),l(this).siblings(".preview-cell-weight-input").select()})},this),this.openSelectedCellStyles(),this.trigger("form_loaded",this)},getSelectedCellIndex:function(){var e=-1;return this.$(".preview-cell .preview-cell-in").each(function(t,i){l(i).is(".cell-selected")&&(e=t)}),e},openSelectedCellStyles:function(){if(!_.isUndefined(this.cellStyles)){if(this.cellStyles.stylesLoaded){var e={};try{e=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",e)}this.cellStyles.detach()}if(this.cellStyles=this.getSelectedCellStyles(),this.cellStyles){var t=this.$(".so-sidebar.so-right-sidebar");this.cellStyles.attach(t),this.cellStyles.stylesLoaded||(this.cellStyles.on("styles_loaded",function(){t.removeClass("so-panels-loading")},this),t.addClass("so-panels-loading"))}},getSelectedCellStyles:function(){var e=this.getSelectedCellIndex();if(e>-1){var t=this.cellStylesCache[e];t||(t=new s.view.styles,t.model=this.row.cells.at(e),t.render("cell",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this,index:e}),this.cellStylesCache[e]=t)}return t},clearCellStylesCache:function(){this.cellStylesCache.forEach(function(e){e.remove()}),this.cellStylesCache=[]},scaleRowWidths:function(){var e=this;this.$(".row-preview .preview-cell").each(function(t,i){var s=e.row.cells.at(t);l(i).css("width",100*s.get("weight")+"%").find(".preview-cell-weight").html(Math.round(1e3*s.get("weight"))/10)})},setCellsFromForm:function(){try{var e={cells:parseInt(this.$('.row-set-form input[name="cells"]').val()),ratio:parseFloat(this.$('.row-set-form select[name="ratio"]').val()),direction:this.$('.row-set-form select[name="ratio_direction"]').val()};_.isNaN(e.cells)&&(e.cells=1),isNaN(e.ratio)&&(e.ratio=1),e.cells<1?(e.cells=1,this.$('.row-set-form input[name="cells"]').val(e.cells)):e.cells>12&&(e.cells=12,this.$('.row-set-form input[name="cells"]').val(e.cells)),this.$('.row-set-form select[name="ratio"]').val(e.ratio);for(var t=[],i=this.row.cells.length!==e.cells,o=1,n=0;n<e.cells;n++)t.push(o),o*=e.ratio;var a=_.reduce(t,function(e,t){return e+t});if(t=_.map(t,function(e){return e/a}),t=_.filter(t,function(e){return e>.01}),"left"===e.direction&&(t=t.reverse()),this.row.cells=new s.collection.cells(this.row.cells.first(t.length)),_.each(t,function(e,t){var i=this.row.cells.at(t);i?i.set("weight",e):(i=new s.model.cell({weight:e,row:this.model}),this.row.cells.add(i))}.bind(this)),this.row.ratio=e.ratio,this.row.ratio_direction=e.direction,i)this.regenerateRowPreview();else{var r=this;this.$(".preview-cell").each(function(e,t){var i=r.row.cells.at(e).get("weight");l(t).animate({width:Math.round(1e3*i)/10+"%"},250),l(t).find(".preview-cell-weight").html(Math.round(1e3*i)/10)}),this.$(".preview-cell").css("overflow","visible"),setTimeout(function(){r.regenerateRowPreview()},260)}}catch(e){console.log("Error setting cells - "+e.message)}this.$(".row-set-form .so-button-row-set").removeClass("button-primary")},tabClickHandler:function(e){"#row-layout"===e.attr("href")?this.$(".so-panels-dialog").addClass("so-panels-dialog-has-right-sidebar"):this.$(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar")},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),_.isEmpty(this.model)||(this.model.setCells(this.row.cells),this.model.set("ratio",this.row.ratio),this.model.set("ratio_direction",this.row.ratio_direction)),!_.isUndefined(this.styles)&&this.styles.stylesLoaded){var t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-row-styles").style}catch(e){console.log("Error retrieving row styles - "+e.message)}this.model.set("style",t)}if(!_.isUndefined(this.cellStyles)&&this.cellStyles.stylesLoaded){var t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",t)}e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},insertHandler:function(){this.builder.addHistoryEntry("row_added"),this.updateModel();var e=this.builder.getActiveCell({createCell:!1}),t={};return null!==e&&(t.at=this.builder.model.get("rows").indexOf(e.row)+1),this.model.collection=this.builder.model.get("rows"),this.builder.model.get("rows").add(this.model,t),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},saveHandler:function(){return this.builder.addHistoryEntry("row_edited"),this.updateModel(),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},deleteHandler:function(){return this.model.trigger("visual_destroy"),this.closeDialog({silent:!0}),!1},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);return this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.closeDialog({silent:!0}),!1},closeHandler:function(){this.clearCellStylesCache(),_.isUndefined(this.cellStyles)||(this.cellStyles=void 0)}})},{}],9:[function(e,t,i){var s=window.panels,l=jQuery,o=e("../view/widgets/js-widget");t.exports=s.view.dialog.extend({builder:null,sidebarWidgetTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-widget-sidebar-widget").html())),dialogClass:"so-panels-dialog-edit-widget",dialogIcon:"add-widget",widgetView:!1,savingWidget:!1,editableLabel:!0,events:{"click .so-close":"saveHandler","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler"},initializeDialog:function(){var e=this;this.model.on("change:values",this.handleChangeValues,this),this.model.on("destroy",this.remove,this),this.dialogFormsLoaded=0,this.on("form_loaded styles_loaded",function(){2===++this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("edit_label",function(e){e===panelsOptions.widgets[this.model.get("class")].title&&(e=""),this.model.set("label",e),_.isEmpty(e)&&this.$(".so-title").text(this.model.getWidgetField("title"))}.bind(this))},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-widget").html(),{})),this.loadForm();var e=this.model.getWidgetField("title");this.$(".so-title .widget-name").html(e),this.$(".so-edit-title").val(e),this.builder.supports("addWidget")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteWidget")||this.$(".so-buttons .so-delete").remove(),this.styles=new s.view.styles,this.styles.model=this.model,this.styles.render("widget",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this});var t=this.$(".so-sidebar.so-right-sidebar");this.styles.attach(t),this.styles.on("styles_loaded",function(e){e?t.removeClass("so-panels-loading"):(t.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),t.remove())},this),t.addClass("so-panels-loading")},getPrevDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t=e.index(this.widgetView.$el);if(0===t)return!1;do{if(widgetView=e.eq(--t).data("view"),!_.isUndefined(widgetView)&&!widgetView.model.get("read_only"))return widgetView.getEditDialog()}while(!_.isUndefined(widgetView)&&t>0);return!1},getNextDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t,i=e.index(this.widgetView.$el);if(i===e.length-1)return!1;do{if(t=e.eq(++i).data("view"),!_.isUndefined(t)&&!t.model.get("read_only"))return t.getEditDialog()}while(!_.isUndefined(t));return!1},loadForm:function(){if(this.$("> *").length){this.$(".so-content").addClass("so-panels-loading");var e={action:"so_panels_widget_form",widget:this.model.get("class"),instance:JSON.stringify(this.model.get("values")),raw:this.model.get("raw")};l.post(panelsOptions.ajaxurl,e,function(e){var t=e.replace(/{\$id}/g,this.model.cid),i=this.$(".so-content");i.removeClass("so-panels-loading").html(t),this.trigger("form_loaded",this),this.$(".panel-dialog").trigger("panelsopen"),this.on("close_dialog",this.updateModel,this),i.find("> .widget-content").length>0&&o.addWidget(i,this.model.widget_id)}.bind(this),"html")}},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),this.savingWidget=!0,!this.model.get("missing")){var t=this.getFormValues();_.isUndefined(t.widgets)?t={}:(t=t.widgets,t=t[Object.keys(t)[0]]),this.model.setValues(t),this.model.set("raw",!0)}if(this.styles.stylesLoaded){var i={};try{i=this.getFormValues(".so-sidebar .so-visual-styles").style}catch(e){}this.model.set("style",i)}this.savingWidget=!1,e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},handleChangeValues:function(){this.savingWidget||this.loadForm()},saveHandler:function(){this.builder.addHistoryEntry("widget_edited"),this.closeDialog()},deleteHandler:function(){return this.model.trigger("visual_destroy"),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1},duplicateHandler:function(){return this.model.trigger("user_duplicate"),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1}})},{"../view/widgets/js-widget":31}],10:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({builder:null,widgetTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-widgets-widget").html())),filter:{},dialogClass:"so-panels-dialog-add-widget",dialogIcon:"add-widget",events:{"click .so-close":"closeDialog","click .widget-type":"widgetClickHandler","keyup .so-sidebar-search":"searchHandler"},initializeDialog:function(){this.on("open_dialog",function(){this.filter.search="",this.filterWidgets(this.filter)},this),this.on("open_dialog_complete",function(){this.$(".so-sidebar-search").val("").focus(),this.balanceWidgetHeights()}),this.on("tab_click",this.tabClickHandler,this)},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-widgets").html(),{})),_.each(panelsOptions.widgets,function(e){var t=l(this.widgetTemplate({title:e.title,description:e.description}));_.isUndefined(e.icon)&&(e.icon="dashicons dashicons-admin-generic"),l('<span class="widget-icon" />').addClass(e.icon).prependTo(t.find(".widget-type-wrapper")),t.data("class",e.class).appendTo(this.$(".widget-type-list"))},this);var e=this.$(".so-sidebar-tabs");_.each(panelsOptions.widget_dialog_tabs,function(t){l(this.dialogTabTemplate({title:t.title})).data({message:t.message,filter:t.filter}).appendTo(e)},this),this.initTabs();var t=this;l(window).resize(function(){t.balanceWidgetHeights()})},tabClickHandler:function(e){this.filter=e.parent().data("filter"),this.filter.search=this.$(".so-sidebar-search").val();var t=e.parent().data("message");return _.isEmpty(t)&&(t=""),this.$(".so-toolbar .so-status").html(t),this.filterWidgets(this.filter),!1},searchHandler:function(e){if(13===e.which){var t=this.$(".widget-type-list .widget-type:visible");1===t.length&&t.click()}else this.filter.search=l(e.target).val().trim(),this.filterWidgets(this.filter)},filterWidgets:function(e){_.isUndefined(e)&&(e={}),_.isUndefined(e.groups)&&(e.groups=""),this.$(".widget-type-list .widget-type").each(function(){var t,i=l(this),s=i.data("class"),o=_.isUndefined(panelsOptions.widgets[s])?null:panelsOptions.widgets[s];t=!!_.isEmpty(e.groups)||null!==o&&!_.isEmpty(_.intersection(e.groups,panelsOptions.widgets[s].groups)),t&&(_.isUndefined(e.search)||""===e.search||-1===o.title.toLowerCase().indexOf(e.search.toLowerCase())&&(t=!1)),t?i.show():i.hide()}),this.balanceWidgetHeights()},
2
  widgetClickHandler:function(e){this.builder.addHistoryEntry("widget_added");var t=l(e.currentTarget),i=new s.model.widget({class:t.data("class")});i.cell=this.builder.getActiveCell(),i.cell.get("widgets").add(i),this.closeDialog(),this.builder.model.refreshPanelsData()},balanceWidgetHeights:function(e){var t=[[]],i=null,s=Math.round(this.$(".widget-type").parent().width()/this.$(".widget-type").width());this.$(".widget-type").css("clear","none").filter(":visible").each(function(e,t){e%s==0&&0!==e&&l(t).css("clear","both")}),this.$(".widget-type-wrapper").css("height","auto").filter(":visible").each(function(e,s){var o=l(s);null!==i&&i.position().top!==o.position().top&&(t[t.length]=[]),i=o,t[t.length-1].push(o)}),_.each(t,function(e,t){var i=_.max(e.map(function(e){return e.height()}));_.each(e,function(e){e.height(i)})})}})},{}],11:[function(e,t,i){t.exports={canCopyPaste:function(){return"undefined"!=typeof Storage&&panelsOptions.user},setModel:function(e){if(!this.canCopyPaste())return!1;var t=panels.helpers.serialize.serialize(e);return e instanceof panels.model.row?t.thingType="row-model":e instanceof panels.model.widget&&(t.thingType="widget-model"),localStorage["panels_clipboard_"+panelsOptions.user]=JSON.stringify(t),!0},isModel:function(e){if(!this.canCopyPaste())return!1;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&(t=JSON.parse(t),t.thingType&&t.thingType===e)},getModel:function(e){if(!this.canCopyPaste())return null;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&(t=JSON.parse(t),t.thingType&&t.thingType===e)?panels.helpers.serialize.unserialize(t,t.thingType,null):null}}},{}],12:[function(e,t,i){t.exports={lock:function(){if("hidden"!==jQuery("body").css("overflow")){var e=[self.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft,self.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop];jQuery("body").data({"scroll-position":e}).css("overflow","hidden"),_.isUndefined(e)||window.scrollTo(e[0],e[1])}},unlock:function(){if("hidden"===jQuery("body").css("overflow")&&!jQuery(".so-panels-dialog-wrapper").is(":visible")&&!jQuery(".so-panels-live-editor").is(":visible")){jQuery("body").css("overflow","visible");var e=jQuery("body").data("scroll-position");_.isUndefined(e)||window.scrollTo(e[0],e[1])}}}},{}],13:[function(e,t,i){t.exports={serialize:function(e){var t;if(e instanceof Backbone.Model){var i={};for(var s in e.attributes)if(e.attributes.hasOwnProperty(s)){if("builder"===s||"collection"===s)continue;t=e.attributes[s],t instanceof Backbone.Model||t instanceof Backbone.Collection?i[s]=this.serialize(t):i[s]=t}return i}if(e instanceof Backbone.Collection){for(var l=[],o=0;o<e.models.length;o++)t=e.models[o],t instanceof Backbone.Model||t instanceof Backbone.Collection?l.push(this.serialize(t)):l.push(t);return l}},unserialize:function(e,t,i){var s;switch(t){case"row-model":s=new panels.model.row,s.builder=i,s.set("style",e.style),s.setCells(this.unserialize(e.cells,"cell-collection",s));break;case"cell-model":s=new panels.model.cell,s.row=i,s.set("weight",e.weight),s.set("style",e.style),s.set("widgets",this.unserialize(e.widgets,"widget-collection",s));break;case"widget-model":s=new panels.model.widget,s.cell=i;for(var l in e)e.hasOwnProperty(l)&&s.set(l,e[l]);s.set("widget_id",panels.helpers.utils.generateUUID());break;case"cell-collection":s=new panels.collection.cells;for(var o=0;o<e.length;o++)s.push(this.unserialize(e[o],"cell-model",i));break;case"widget-collection":s=new panels.collection.widgets;for(var o=0;o<e.length;o++)s.push(this.unserialize(e[o],"widget-model",i));break;default:console.log("Unknown Thing - "+t)}return s}}},{}],14:[function(e,t,i){t.exports={generateUUID:function(){var e=(new Date).getTime();return window.performance&&"function"==typeof window.performance.now&&(e+=performance.now()),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var i=(e+16*Math.random())%16|0;return e=Math.floor(e/16),("x"==t?i:3&i|8).toString(16)})},processTemplate:function(e){return _.isUndefined(e)||_.isNull(e)?"":(e=e.replace(/{{%/g,"<%"),e=e.replace(/%}}/g,"%>"),e=e.trim())},selectElementContents:function(e){var t=document.createRange();t.selectNodeContents(e);var i=window.getSelection();i.removeAllRanges(),i.addRange(t)}}},{}],15:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=function(e){return this.each(function(){var t=jQuery(this),i=t.closest("form").find(".widget-id").val(),o=l.extend(!0,{},e);if(_.isUndefined(i)||!(i.indexOf("__i__")>-1)){var n=new s.model.builder,a=new s.view.builder({model:n,config:o}),r=t.closest(".so-panels-dialog-wrapper").data("view");_.isUndefined(r)||(r.on("close_dialog",function(){n.refreshPanelsData()}),r.on("open_dialog_complete",function(){a.trigger("builder_resize")}),r.model.on("destroy",function(){n.emptyRows().destroy()}),a.setDialogParents(panelsOptions.loc.layout_widget,r));var d=Boolean(t.closest(".widget-content").length);a.render().attach({container:t,dialog:d||"dialog"===t.data("mode"),type:t.data("type")}).setDataField(t.find("input.panels-data")),d||"dialog"===t.data("mode")?(a.setDialogParents(panelsOptions.loc.layout_widget,a.dialog),t.find(".siteorigin-panels-display-builder").click(function(e){e.preventDefault(),a.dialog.openDialog()})):t.find(".siteorigin-panels-display-builder").parent().remove(),l(document).trigger("panels_setup",a)}})}},{}],16:[function(e,t,i){var s={};window.panels=s,window.siteoriginPanels=s,s.helpers={},s.helpers.clipboard=e("./helpers/clipboard"),s.helpers.utils=e("./helpers/utils"),s.helpers.serialize=e("./helpers/serialize"),s.helpers.pageScroll=e("./helpers/page-scroll"),s.model={},s.model.widget=e("./model/widget"),s.model.cell=e("./model/cell"),s.model.row=e("./model/row"),s.model.builder=e("./model/builder"),s.model.historyEntry=e("./model/history-entry"),s.collection={},s.collection.widgets=e("./collection/widgets"),s.collection.cells=e("./collection/cells"),s.collection.rows=e("./collection/rows"),s.collection.historyEntries=e("./collection/history-entries"),s.view={},s.view.widget=e("./view/widget"),s.view.cell=e("./view/cell"),s.view.row=e("./view/row"),s.view.builder=e("./view/builder"),s.view.dialog=e("./view/dialog"),s.view.styles=e("./view/styles"),s.view.liveEditor=e("./view/live-editor"),s.dialog={},s.dialog.builder=e("./dialog/builder"),s.dialog.widgets=e("./dialog/widgets"),s.dialog.widget=e("./dialog/widget"),s.dialog.prebuilt=e("./dialog/prebuilt"),s.dialog.row=e("./dialog/row"),s.dialog.history=e("./dialog/history"),s.utils={},s.utils.menu=e("./utils/menu"),jQuery.fn.soPanelsSetupBuilderWidget=e("./jquery/setup-builder-widget"),jQuery(function(e){var t,i,s,l,o=e("#siteorigin-panels-metabox");if(s=e("form#post"),o.length&&s.length)t=o,i=o.find(".siteorigin-panels-data-field"),l={editorType:"tinyMCE",postId:e("#post_ID").val(),editorId:"#content",builderType:o.data("builder-type"),builderSupports:o.data("builder-supports"),loadOnAttach:panelsOptions.loadOnAttach&&1==e("#auto_draft").val(),loadLiveEditor:1==o.data("live-editor"),liveEditorPreview:t.data("preview-url")};else if(e(".siteorigin-panels-builder-form").length){var n=e(".siteorigin-panels-builder-form");t=n.find(".siteorigin-panels-builder-container"),i=n.find('input[name="panels_data"]'),s=n,l={editorType:"standalone",postId:n.data("post-id"),editorId:"#post_content",builderType:n.data("type"),builderSupports:n.data("builder-supports"),loadLiveEditor:!1,liveEditorPreview:n.data("preview-url")}}if(!_.isUndefined(t)){var a=window.siteoriginPanels,r=new a.model.builder,d=new a.view.builder({model:r,config:l});d.render().attach({container:t}).setDataField(i).attachToEditor(),s.submit(function(){r.refreshPanelsData()}),t.removeClass("so-panels-loading"),e(document).trigger("panels_setup",d,window.panels)}e(document).on("widget-added",function(t,i){e(i).find(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()}),e("body").hasClass("wp-customizer")||e(function(){e(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()})})},{"./collection/cells":1,"./collection/history-entries":2,"./collection/rows":3,"./collection/widgets":4,"./dialog/builder":5,"./dialog/history":6,"./dialog/prebuilt":7,"./dialog/row":8,"./dialog/widget":9,"./dialog/widgets":10,"./helpers/clipboard":11,"./helpers/page-scroll":12,"./helpers/serialize":13,"./helpers/utils":14,"./jquery/setup-builder-widget":15,"./model/builder":17,"./model/cell":18,"./model/history-entry":19,"./model/row":20,"./model/widget":21,"./utils/menu":22,"./view/builder":23,"./view/cell":24,"./view/dialog":25,"./view/live-editor":26,"./view/row":27,"./view/styles":28,"./view/widget":29}],17:[function(e,t,i){t.exports=Backbone.Model.extend({layoutPosition:{BEFORE:"before",AFTER:"after",REPLACE:"replace"},rows:{},defaults:{data:{widgets:[],grids:[],grid_cells:[]}},initialize:function(){this.set("rows",new panels.collection.rows)},addRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var s=new panels.collection.cells(t);e=_.extend({collection:this.get("rows"),cells:s},e);var l=new panels.model.row(e);return l.builder=this,this.get("rows").add(l,i),l},loadPanelsData:function(e,t){try{t===this.layoutPosition.BEFORE?e=this.concatPanelsData(e,this.getPanelsData()):t===this.layoutPosition.AFTER&&(e=this.concatPanelsData(this.getPanelsData(),e)),this.emptyRows(),this.set("data",JSON.parse(JSON.stringify(e)),{silent:!0});var i=[];if(_.isUndefined(e.grid_cells))return void this.trigger("load_panels_data");for(var s,l=0;l<e.grid_cells.length;l++)s=parseInt(e.grid_cells[l].grid),_.isUndefined(i[s])&&(i[s]=[]),i[s].push(e.grid_cells[l]);var o=this;if(_.each(i,function(t,i){var s={};_.isUndefined(e.grids[i].style)||(s.style=e.grids[i].style),_.isUndefined(e.grids[i].ratio)||(s.ratio=e.grids[i].ratio),_.isUndefined(e.grids[i].ratio_direction)||(s.ratio_direction=e.grids[i].ratio_direction),_.isUndefined(e.grids[i].color_label)||(s.color_label=e.grids[i].color_label),_.isUndefined(e.grids[i].label)||(s.label=e.grids[i].label),o.addRow(s,t,{noAnimate:!0})}),_.isUndefined(e.widgets))return;_.each(e.widgets,function(e){var t=null;_.isUndefined(e.panels_info)?(t=e.info,delete e.info):(t=e.panels_info,delete e.panels_info);var i=o.get("rows").at(parseInt(t.grid)),s=i.get("cells").at(parseInt(t.cell)),l=new panels.model.widget({class:t.class,values:e});_.isUndefined(t.style)||l.set("style",t.style),_.isUndefined(t.read_only)||l.set("read_only",t.read_only),_.isUndefined(t.widget_id)?l.set("widget_id",panels.helpers.utils.generateUUID()):l.set("widget_id",t.widget_id),_.isUndefined(t.label)||l.set("label",t.label),l.cell=s,s.get("widgets").add(l,{noAnimate:!0})}),this.trigger("load_panels_data")}catch(e){console.log("Error loading data: "+e.message)}},concatPanelsData:function(e,t){if(_.isUndefined(t)||_.isUndefined(t.grids)||_.isEmpty(t.grids)||_.isUndefined(t.grid_cells)||_.isEmpty(t.grid_cells))return e;if(_.isUndefined(e)||_.isUndefined(e.grids)||_.isEmpty(e.grids))return t;var i=e.grids.length,s=_.isUndefined(e.widgets)?0:e.widgets.length,l={grids:[],grid_cells:[],widgets:[]};l.grids=e.grids.concat(t.grids),_.isUndefined(e.grid_cells)||(l.grid_cells=e.grid_cells.slice()),_.isUndefined(e.widgets)||(l.widgets=e.widgets.slice());var o;for(o=0;o<t.grid_cells.length;o++){var n=t.grid_cells[o];n.grid=parseInt(n.grid)+i,l.grid_cells.push(n)}if(!_.isUndefined(t.widgets))for(o=0;o<t.widgets.length;o++){var a=t.widgets[o];a.panels_info.grid=parseInt(a.panels_info.grid)+i,a.panels_info.id=parseInt(a.panels_info.id)+s,l.widgets.push(a)}return l},getPanelsData:function(){var e={widgets:[],grids:[],grid_cells:[]},t=0;return this.get("rows").each(function(i,s){i.get("cells").each(function(i,l){i.get("widgets").each(function(i,o){var n={class:i.get("class"),raw:i.get("raw"),grid:s,cell:l,id:t++,widget_id:i.get("widget_id"),style:i.get("style"),label:i.get("label")};_.isEmpty(n.widget_id)&&(n.widget_id=panels.helpers.utils.generateUUID());var a=_.extend(_.clone(i.get("values")),{panels_info:n});e.widgets.push(a)}),e.grid_cells.push({grid:s,index:l,weight:i.get("weight"),style:i.get("style")})}),e.grids.push({cells:i.get("cells").length,style:i.get("style"),ratio:i.get("ratio"),ratio_direction:i.get("ratio_direction"),color_label:i.get("color_label"),label:i.get("label")})}),e},refreshPanelsData:function(e){e=_.extend({silent:!1},e);var t=this.get("data"),i=this.getPanelsData();this.set("data",i,{silent:!0}),e.silent||JSON.stringify(i)===JSON.stringify(t)||(this.trigger("change"),this.trigger("change:data"),this.trigger("refresh_panels_data",i,e))},emptyRows:function(){return _.invoke(this.get("rows").toArray(),"destroy"),this.get("rows").reset(),this},isValidLayoutPosition:function(e){return e===this.layoutPosition.BEFORE||e===this.layoutPosition.AFTER||e===this.layoutPosition.REPLACE},getPanelsDataFromHtml:function(e,t){var i=this,s=jQuery('<div id="wrapper">'+e+"</div>");if(s.find(".panel-layout .panel-grid").length){var l={grids:[],grid_cells:[],widgets:[]},o=new RegExp(panelsOptions.siteoriginWidgetRegex,"i"),n=function(){function e(e){return e&&"string"==typeof e&&(e=e.replace(/<script[^>]*>([\S\s]*?)<\/script>/gim,""),e=e.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gim,""),t.innerHTML=e,e=t.textContent,t.textContent=""),e}var t=document.createElement("div");return e}(),a=function(e){var t=e.find("div");if(!t.length)return e.html();var i;for(i=0;i<t.length-1&&jQuery.trim(t.eq(i).text())==jQuery.trim(t.eq(i+1).text());i++);var s=t.eq(i).find(".widget-title:header"),l="";return s.length&&(l=s.html(),s.remove()),{title:l,text:t.eq(i).html()}},r=s.find(".panel-layout").eq(0),d=function(e,t){return jQuery(t).closest(".panel-layout").is(r)};return s.find("> .panel-layout > .panel-grid").filter(d).each(function(e,s){var r=jQuery(s),c=r.find(".panel-grid-cell").filter(d);l.grids.push({cells:c.length,style:r.data("style"),ratio:r.data("ratio"),ratio_direction:r.data("ratio-direction"),color_label:r.data("color-label"),label:r.data("label")}),c.each(function(s,r){var c=jQuery(r),h=c.find(".so-panel").filter(d);l.grid_cells.push({grid:e,weight:_.isUndefined(c.data("weight"))?1:parseFloat(c.data("weight")),style:c.data("style")}),h.each(function(r,d){var c=jQuery(d),h=c.find(".panel-widget-style").length?c.find(".panel-widget-style").html():c.html(),u={grid:e,cell:s,style:c.data("style"),raw:!1,label:c.data("label")};h=h.trim();var p=o.exec(h);if(!_.isNull(p)&&""===h.replace(o,"").trim()){try{var g=/class="(.*?)"/.exec(p[3]),f=jQuery(p[5]),w=JSON.parse(n(f.val())),m=w.instance;u.class=g[1].replace(/\\\\+/g,"\\"),u.raw=!1,m.panels_info=u,l.widgets.push(m)}catch(e){u.class=t,l.widgets.push(_.extend(a(c),{filter:"1",type:"visual",panels_info:u}))}return!0}if(-1!==h.indexOf("panel-layout")){if(jQuery("<div>"+h+"</div>").find(".panel-layout .panel-grid").length)return u.class="SiteOrigin_Panels_Widgets_Layout",l.widgets.push({panels_data:i.getPanelsDataFromHtml(h,t),panels_info:u}),!0}return u.class=t,l.widgets.push(_.extend(a(c),{filter:"1",type:"visual",panels_info:u})),!0})})}),s.find(".panel-layout").remove(),s.find("style[data-panels-style-for-post]").remove(),s.html().replace(/^\s+|\s+$/gm,"").length&&(l.grids.push({cells:1,style:{}}),l.grid_cells.push({grid:l.grids.length-1,weight:1}),l.widgets.push({filter:"1",text:s.html().replace(/^\s+|\s+$/gm,""),title:"",type:"visual",panels_info:{class:t,raw:!1,grid:l.grids.length-1,cell:0}})),l}return{grid_cells:[{grid:0,weight:1}],grids:[{cells:1}],widgets:[{filter:"1",text:e,title:"",type:"visual",panels_info:{class:t,raw:!1,grid:0,cell:0}}]}}})},{}],18:[function(e,t,i){t.exports=Backbone.Model.extend({widgets:{},row:null,defaults:{weight:0,style:{}},indexes:null,initialize:function(){this.set("widgets",new panels.collection.widgets),this.on("destroy",this.onDestroy,this)},onDestroy:function(){_.invoke(this.get("widgets").toArray(),"destroy"),this.get("widgets").reset()},clone:function(e,t){_.isUndefined(e)&&(e=this.row),t=_.extend({cloneWidgets:!0},t);var i=new this.constructor(this.attributes);return i.set("collection",e.get("cells"),{silent:!0}),i.row=e,t.cloneWidgets&&this.get("widgets").each(function(e){i.get("widgets").add(e.clone(i,t),{silent:!0})}),i}})},{}],19:[function(e,t,i){t.exports=Backbone.Model.extend({defaults:{text:"",data:"",time:null,count:1}})},{}],20:[function(e,t,i){t.exports=Backbone.Model.extend({builder:null,defaults:{style:{}},indexes:null,initialize:function(){_.isEmpty(this.get("cells"))?this.set("cells",new panels.collection.cells):this.get("cells").each(function(e){e.row=this}.bind(this)),this.on("destroy",this.onDestroy,this)},setCells:function(e){var t=this.get("cells")||new panels.collection.cells,i=[];t.each(function(s,l){var o=e.at(l);if(o)s.set("weight",o.get("weight"));else{for(var n=t.at(e.length-1),a=s.get("widgets").models.slice(),r=0;r<a.length;r++)a[r].moveToCell(n,{silent:!1});i.push(s)}}),_.each(i,function(e){t.remove(e)}),e.length>t.length&&_.each(e.slice(t.length,e.length),function(e){e.set({collection:t}),e.row=this,t.add(e)}.bind(this)),this.reweightCells()},reweightCells:function(){var e=0,t=this.get("cells");t.each(function(t){e+=t.get("weight")}),t.each(function(t){t.set("weight",t.get("weight")/e)}),this.trigger("reweight_cells")},onDestroy:function(){_.invoke(this.get("cells").toArray(),"destroy"),this.get("cells").reset()},clone:function(e){_.isUndefined(e)&&(e=this.builder);var t=new this.constructor(this.attributes);t.set("collection",e.get("rows"),{silent:!0}),t.builder=e;var i=new panels.collection.cells;return this.get("cells").each(function(e){i.add(e.clone(t),{silent:!0})}),t.set("cells",i),t}})},{}],21:[function(e,t,i){t.exports=Backbone.Model.extend({cell:null,defaults:{class:null,missing:!1,values:{},raw:!1,style:{},read_only:!1,widget_id:""},indexes:null,initialize:function(){var e=this.get("class");!_.isUndefined(panelsOptions.widgets[e])&&panelsOptions.widgets[e].installed||this.set("missing",!0)},getWidgetField:function(e){return _.isUndefined(panelsOptions.widgets[this.get("class")])?"title"===e||"description"===e?panelsOptions.loc.missing_widget[e]:"":this.has("label")&&!_.isEmpty(this.get("label"))?this.get("label"):panelsOptions.widgets[this.get("class")][e]},moveToCell:function(e,t,i){return t=_.extend({silent:!0},t),this.cell=e,this.collection.remove(this,t),e.get("widgets").add(this,_.extend({at:i},t)),this.trigger("move_to_cell",e,i),this},triggerEdit:function(){this.trigger("user_edit",this)},triggerDuplicate:function(){this.trigger("user_duplicate",this)},setValues:function(e){var t=!1;JSON.stringify(e)!==JSON.stringify(this.get("values"))&&(t=!0),this.set("values",e,{silent:!0}),t&&(this.trigger("change",this),this.trigger("change:values"))},clone:function(e,t){_.isUndefined(e)&&(e=this.cell);var i=new this.constructor(this.attributes),s=JSON.parse(JSON.stringify(this.get("values"))),l=function(e){return _.each(e,function(t,i){_.isString(i)&&"_"===i[0]?delete e[i]:_.isObject(e[i])&&l(e[i])}),e};return s=l(s),"SiteOrigin_Panels_Widgets_Layout"===this.get("class")&&(s.builder_id=Math.random().toString(36).substr(2)),i.set("widget_id",""),i.set("values",s,{silent:!0}),i.set("collection",e.get("widgets"),{silent:!0}),i.cell=e,i.isDuplicate=!0,i},getTitle:function(){var e=panelsOptions.widgets[this.get("class")];if(_.isUndefined(e))return this.get("class").replace(/_/g," ");if(!_.isUndefined(e.panels_title)&&!1===e.panels_title)return panelsOptions.widgets[this.get("class")].description;var t=this.get("values"),i=["title","text"];for(var s in t)t.hasOwnProperty(s)&&i.push(s);i=_.uniq(i);for(var l in i)if(!_.isUndefined(t[i[l]])&&_.isString(t[i[l]])&&""!==t[i[l]]&&"on"!==t[i[l]]&&"_"!==i[l][0]&&!jQuery.isNumeric(t[i[l]])){var o=t[i[l]];o=o.replace(/<\/?[^>]+(>|$)/g,"");var n=o.split(" ");return n=n.slice(0,20),n.join(" ")}return this.getWidgetField("description")}})},{}],22:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({wrapperTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-context-menu").html())),sectionTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-context-menu-section").html())),contexts:[],active:!1,events:{"keyup .so-search-wrapper input":"searchKeyUp"},initialize:function(){this.listenContextMenu(),this.render(),this.attach()},listenContextMenu:function(){var e=this;l(window).on("contextmenu",function(t){return e.active&&!e.isOverEl(e.$el,t)?(e.closeMenu(),e.active=!1,t.preventDefault(),!1):!!e.active||(e.active=!1,e.trigger("activate_context",t,e),void(e.active&&(t.preventDefault(),e.openMenu({left:t.pageX,top:t.pageY}))))})},render:function(){this.setElement(this.wrapperTemplate())},attach:function(){this.$el.appendTo("body")},openMenu:function(e){this.trigger("open_menu"),l(window).on("keyup",{menu:this},this.keyboardListen),l(window).on("click",{menu:this},this.clickOutsideListen),this.$el.css("max-height",l(window).height()-20),e.left+this.$el.outerWidth()+10>=l(window).width()&&(e.left=l(window).width()-this.$el.outerWidth()-10),e.left<=0&&(e.left=10),e.top+this.$el.outerHeight()-l(window).scrollTop()+10>=l(window).height()&&(e.top=l(window).height()+l(window).scrollTop()-this.$el.outerHeight()-10),e.left<=0&&(e.left=10),this.$el.css({left:e.left+1,top:e.top+1}).show(),this.$(".so-search-wrapper input").focus()},closeMenu:function(){this.trigger("close_menu"),l(window).off("keyup",this.keyboardListen),l(window).off("click",this.clickOutsideListen),this.active=!1,this.$el.empty().hide()},keyboardListen:function(e){var t=e.data.menu;switch(e.which){case 27:t.closeMenu()}},clickOutsideListen:function(e){var t=e.data.menu;3!==e.which&&t.$el.is(":visible")&&!t.isOverEl(t.$el,e)&&t.closeMenu()},addSection:function(e,t,i,s){var o=this;t=_.extend({display:5,defaultDisplay:!1,search:!0,sectionTitle:"",searchPlaceholder:"",titleKey:"title"},t);var n=l(this.sectionTemplate({settings:t,items:i})).attr("id","panels-menu-section-"+e);this.$el.append(n),n.find(".so-item:not(.so-confirm)").click(function(){var e=l(this);s(e.data("key")),o.closeMenu()}),n.find(".so-item.so-confirm").click(function(){var e=l(this);if(e.hasClass("so-confirming"))return s(e.data("key")),void o.closeMenu();e.data("original-text",e.html()).addClass("so-confirming").html('<span class="dashicons dashicons-yes"></span> '+panelsOptions.loc.dropdown_confirm),setTimeout(function(){e.removeClass("so-confirming"),e.html(e.data("original-text"))},2500)}),n.data("settings",t).find(".so-search-wrapper input").trigger("keyup"),this.active=!0},hasSection:function(e){return this.$el.find("#panels-menu-section-"+e).length>0},searchKeyUp:function(e){var t=l(e.currentTarget),i=t.closest(".so-section"),s=i.data("settings");if(38===e.which||40===e.which){var o=i.find("ul li:visible"),n=o.filter(".so-active").eq(0);if(n.length){o.removeClass("so-active");var a=o.index(n);38===e.which?n=a-1<0?o.last():o.eq(a-1):40===e.which&&(n=a+1>=o.length?o.first():o.eq(a+1))}else 38===e.which?n=o.last():40===e.which&&(n=o.first());return n.addClass("so-active"),!1}if(13===e.which)return 1===i.find("ul li:visible").length?(i.find("ul li:visible").trigger("click"),!1):(i.find("ul li.so-active:visible").trigger("click"),!1);if(""===t.val())if(s.defaultDisplay){i.find(".so-item").hide();for(var r=0;r<s.defaultDisplay.length;r++)i.find('.so-item[data-key="'+s.defaultDisplay[r]+'"]').show()}else i.find(".so-item").show();else i.find(".so-item").hide().each(function(){var e=l(this);-1!==e.html().toLowerCase().indexOf(t.val().toLowerCase())&&e.show()});i.find(".so-item:visible:gt("+(s.display-1)+")").hide(),0===i.find(".so-item:visible").length&&""!==t.val()?i.find(".so-no-results").show():i.find(".so-no-results").hide()},isOverEl:function(e,t){var i=[[e.offset().left,e.offset().top],[e.offset().left+e.outerWidth(),e.offset().top+e.outerHeight()]];return t.pageX>=i[0][0]&&t.pageX<=i[1][0]&&t.pageY>=i[0][1]&&t.pageY<=i[1][1]}})},{}],23:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({config:{},template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder").html())),dialogs:{},rowsSortable:null,dataField:!1,currentData:"",attachedToEditor:!1,attachedVisible:!1,liveEditor:void 0,menu:!1,activeCell:null,events:{"click .so-tool-button.so-widget-add":"displayAddWidgetDialog","click .so-tool-button.so-row-add":"displayAddRowDialog","click .so-tool-button.so-prebuilt-add":"displayAddPrebuiltDialog","click .so-tool-button.so-history":"displayHistoryDialog","click .so-tool-button.so-live-editor":"displayLiveEditor"},rows:null,initialize:function(e){var t=this;return this.config=_.extend({loadLiveEditor:!1,builderSupports:{}},e.config),this.config.builderSupports=_.extend({addRow:!0,editRow:!0,deleteRow:!0,moveRow:!0,addWidget:!0,editWidget:!0,deleteWidget:!0,moveWidget:!0,prebuilt:!0,history:!0,liveEditor:!0,revertToEditor:!0},this.config.builderSupports),e.config.loadLiveEditor&&this.on("builder_live_editor_added",function(){this.displayLiveEditor()}),this.dialogs={widgets:new s.dialog.widgets,row:new s.dialog.row,prebuilt:new s.dialog.prebuilt},_.each(this.dialogs,function(e,i,s){s[i].setBuilder(t)}),this.dialogs.row.setRowDialogType("create"),this.model.get("rows").on("add",this.onAddRow,this),l(window).resize(function(e){e.target===window&&t.trigger("builder_resize")}),this.model.on("change:data load_panels_data",this.storeModelData,this),this.on("content_change",this.handleContentChange,this),this.on("display_builder",this.handleDisplayBuilder,this),this.on("hide_builder",this.handleHideBuilder,this),this.on("builder_rendered builder_resize",this.handleBuilderSizing,this),this.model.on("change:data load_panels_data",this.toggleWelcomeDisplay,this),this.on("display_builder",this.wrapEditorExpandAdjust,this),this.menu=new s.utils.menu({}),this.menu.on("activate_context",this.activateContextMenu,this),this.config.loadOnAttach&&this.on("builder_attached_to_editor",function(){this.displayAttachedBuilder({confirm:!1})},this),this},render:function(){return this.setElement(this.template()),this.$el.attr("id","siteorigin-panels-builder-"+this.cid).addClass("so-builder-container"),this.trigger("builder_rendered"),this},attach:function(e){e=_.extend({container:!1,dialog:!1},e),e.dialog?(this.dialog=new s.dialog.builder,this.dialog.builder=this):(this.$el.appendTo(e.container),this.metabox=e.container.closest(".postbox"),this.initSortable(),this.trigger("attached_to_container",e.container)),this.trigger("builder_attached"),this.supports("liveEditor")&&this.addLiveEditor(),this.supports("history")&&this.addHistoryBrowser();var t=this.$(".so-builder-toolbar"),i=this.$(".so-panels-welcome-message"),l=panelsOptions.loc.welcomeMessage,o=[];this.supports("addWidget")?o.push(l.addWidgetButton):t.find(".so-widget-add").hide(),this.supports("addRow")?o.push(l.addRowButton):t.find(".so-row-add").hide(),this.supports("prebuilt")?o.push(l.addPrebuiltButton):t.find(".so-prebuilt-add").hide();var n="";3===o.length?n=l.threeEnabled:2===o.length?n=l.twoEnabled:1===o.length?n=l.oneEnabled:0===o.length&&(n=l.addingDisabled);var a=_.template(s.helpers.utils.processTemplate(n)),r=a({items:o})+" "+l.docsMessage;return i.find(".so-message-wrapper").html(r),this},attachToEditor:function(){if("tinyMCE"!==this.config.editorType)return this;this.attachedToEditor=!0;var e=this.metabox,t=this;l("#wp-content-wrap .wp-editor-tabs").find(".wp-switch-editor").click(function(e){e.preventDefault(),l("#wp-content-editor-container").show(),l("#wp-content-wrap").removeClass("panels-active"),l("#content-resize-handle").show(),t.trigger("hide_builder")}).end().append(l('<a id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">'+e.find(".hndle span").html()+"</a>").click(function(e){t.displayAttachedBuilder({confirm:!0})&&e.preventDefault()})),this.supports("revertToEditor")&&e.find(".so-switch-to-standard").click(function(i){i.preventDefault(),confirm(panelsOptions.loc.confirm_stop_builder)&&(t.addHistoryEntry("back_to_editor"),t.model.loadPanelsData(!1),l("#wp-content-wrap").show(),e.hide(),l(window).resize(),t.attachedVisible=!1,t.trigger("hide_builder"))}).show(),e.insertAfter("#wp-content-wrap").hide().addClass("attached-to-editor");var i=this.model.get("data");_.isEmpty(i.widgets)&&_.isEmpty(i.grids)&&this.supports("revertToEditor")||this.displayAttachedBuilder({confirm:!1});var s=function(){var e=t.$(".so-builder-toolbar");if(t.$el.hasClass("so-display-narrow"))return e.css({top:0,left:0,width:"100%",position:"absolute"}),void t.$el.css("padding-top",e.outerHeight());var i=l(window).scrollTop()-t.$el.offset().top;"fixed"===l("#wpadminbar").css("position")&&(i+=l("#wpadminbar").outerHeight());var s={top:0,bottom:t.$el.outerHeight()-e.outerHeight()+20};i>s.top&&i<s.bottom?"fixed"!==e.css("position")&&e.css({top:l("#wpadminbar").outerHeight(),left:t.$el.offset().left,width:t.$el.outerWidth(),position:"fixed"}):e.css({top:Math.min(Math.max(i,0),t.$el.outerHeight()-e.outerHeight()+20),left:0,width:"100%",position:"absolute"}),t.$el.css("padding-top",e.outerHeight())};return this.on("builder_resize",s,this),l(document).scroll(s),s(),this.trigger("builder_attached_to_editor"),this},displayAttachedBuilder:function(e){if(e=_.extend({confirm:!0},e),e.confirm){var t="undefined"!=typeof tinyMCE&&tinyMCE.get("content");if(""!==(t&&_.isFunction(t.getContent)?t.getContent():l("textarea#content").val())&&!confirm(panelsOptions.loc.confirm_use_builder))return!1}return l("#wp-content-wrap").hide(),l("#editor-expand-toggle").on("change.editor-expand",function(){l(this).prop("checked")||l("#wp-content-wrap").hide()}),this.metabox.show().find("> .inside").show(),l(window).resize(),l(document).scroll(),this.attachedVisible=!0,this.trigger("display_builder"),!0},initSortable:function(){if(!this.supports("moveRow"))return this;var e=this;return this.rowsSortable=this.$(".so-rows-container").sortable({appendTo:"#wpwrap",items:".so-row-container",handle:".so-row-move",axis:"y",tolerance:"pointer",scroll:!1,stop:function(t,i){e.addHistoryEntry("row_moved");var s=l(i.item),o=s.data("view");e.model.get("rows").remove(o.model,{silent:!0}),e.model.get("rows").add(o.model,{silent:!0,at:s.index()}),o.trigger("move",s.index()),e.model.refreshPanelsData()}}),this},refreshSortable:function(){_.isNull(this.rowsSortable)||this.rowsSortable.sortable("refresh")},setDataField:function(e,t){if(t=_.extend({load:!0},t),this.dataField=e,this.dataField.data("builder",this),t.load&&""!==e.val()){var i=this.dataField.val();try{i=JSON.parse(i)}catch(e){i={}}this.model.loadPanelsData(i),this.currentData=i,this.toggleWelcomeDisplay()}return this},storeModelData:function(){var e=JSON.stringify(this.model.get("data"));l(this.dataField).val()!==e&&(l(this.dataField).val(e),l(this.dataField).trigger("change"),this.trigger("content_change"))},onAddRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var l=new s.view.row({model:e});l.builder=this,l.render(),_.isUndefined(i.at)||t.length<=1?l.$el.appendTo(this.$(".so-rows-container")):l.$el.insertAfter(this.$(".so-rows-container .so-row-container").eq(i.at-1)),!1===i.noAnimate&&l.visualCreate(),this.refreshSortable(),l.resize()},displayAddWidgetDialog:function(){this.dialogs.widgets.openDialog()},displayAddRowDialog:function(){var e=new s.model.row,t=new s.collection.cells([{weight:.5},{weight:.5}]);t.each(function(t){t.row=e}),e.set("cells",t),e.builder=this.model,this.dialogs.row.setRowModel(e),this.dialogs.row.openDialog()},displayAddPrebuiltDialog:function(){this.dialogs.prebuilt.openDialog()},displayHistoryDialog:function(){this.dialogs.history.openDialog()},pasteRowHandler:function(){var e=s.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof s.model.row&&(this.addHistoryEntry("row_pasted"),e.builder=this.model,this.model.get("rows").add(e,{at:this.model.get("rows").indexOf(this.model)+1}),this.model.refreshPanelsData())},getActiveCell:function(e){if(e=_.extend({createCell:!0},e),
3
- !this.model.get("rows").length){if(!e.createCell)return null;this.model.addRow({},[{weight:1}],{noAnimate:!0})}var t=this.activeCell;return _.isEmpty(t)||-1===this.model.get("rows").indexOf(t.model.row)?this.model.get("rows").last().get("cells").first():t.model},addLiveEditor:function(){return _.isEmpty(this.config.liveEditorPreview)?this:(this.liveEditor=new s.view.liveEditor({builder:this,previewUrl:this.config.liveEditorPreview}),this.liveEditor.hasPreviewUrl()&&this.$(".so-builder-toolbar .so-live-editor").show(),this.trigger("builder_live_editor_added"),this)},displayLiveEditor:function(){_.isUndefined(this.liveEditor)||this.liveEditor.open()},addHistoryBrowser:function(){if(_.isEmpty(this.config.liveEditorPreview))return this;this.dialogs.history=new s.dialog.history,this.dialogs.history.builder=this,this.dialogs.history.entries.builder=this.model,this.dialogs.history.setRevertEntry(this.model),this.$(".so-builder-toolbar .so-history").show()},addHistoryEntry:function(e,t){_.isUndefined(t)&&(t=null),_.isUndefined(this.dialogs.history)||this.dialogs.history.entries.addEntry(e,t)},supports:function(e){return"rowAction"===e?this.supports("addRow")||this.supports("editRow")||this.supports("deleteRow"):"widgetAction"===e?this.supports("addWidget")||this.supports("editWidget")||this.supports("deleteWidget"):!_.isUndefined(this.config.builderSupports[e])&&this.config.builderSupports[e]},handleContentChange:function(){if(panelsOptions.copy_content&&this.attachedToEditor&&this.$el.is(":visible")){var e=this.model.getPanelsData();_.isEmpty(e.widgets)||l.post(panelsOptions.ajaxurl,{action:"so_panels_builder_content",panels_data:JSON.stringify(e),post_id:this.config.postId},function(e){""!==e&&this.updateEditorContent(e)}.bind(this))}},updateEditorContent:function(e){if("tinyMCE"!==this.config.editorType||"undefined"==typeof tinyMCE||_.isNull(tinyMCE.get("content"))){l(this.config.editorId).val(e).trigger("change").trigger("keyup")}else{var t=tinyMCE.get("content");t.setContent(e),t.fire("change"),t.fire("keyup")}this.triggerYoastSeoChange()},triggerYoastSeoChange:function(){if(l("#yoast_wpseo_focuskw_text_input").length){var e,t=document.getElementById("yoast_wpseo_focuskw_text_input");document.createEvent?(e=document.createEvent("HTMLEvents"),e.initEvent("keyup",!0,!0)):(e=document.createEventObject(),e.eventType="keyup"),e.eventName="keyup",document.createEvent?t.dispatchEvent(e):t.fireEvent("on"+e.eventType,e)}},handleDisplayBuilder:function(){var e="undefined"!=typeof tinyMCE&&tinyMCE.get("content"),t=e&&_.isFunction(e.getContent)?e.getContent():l("textarea#content").val();if((_.isEmpty(this.model.get("data"))||_.isEmpty(this.model.get("data").widgets)&&_.isEmpty(this.model.get("data").grids))&&""!==t){var i=panelsOptions.text_widget;if(_.isEmpty(i))return;this.model.loadPanelsData(this.model.getPanelsDataFromHtml(t,i)),this.model.trigger("change"),this.model.trigger("change:data")}l("#post-status-info").addClass("for-siteorigin-panels")},handleHideBuilder:function(){l("#post-status-info").show().removeClass("for-siteorigin-panels")},wrapEditorExpandAdjust:function(){try{for(var e,t=(l.hasData(window)&&l._data(window)).events.scroll,i=0;i<t.length;i++)if("editor-expand"===t[i].namespace){e=t[i],l(window).unbind("scroll",e.handler),l(window).bind("scroll",function(t){this.attachedVisible||e.handler(t)}.bind(this));break}}catch(e){return}},handleBuilderSizing:function(){var e=this.$el.width();return e?(e<480?this.$el.addClass("so-display-narrow"):this.$el.removeClass("so-display-narrow"),this):this},setDialogParents:function(e,t){_.each(this.dialogs,function(i,s,l){l[s].setParent(e,t)}),this.on("add_dialog",function(i){i.setParent(e,t)},this)},toggleWelcomeDisplay:function(){this.model.get("rows").isEmpty()?this.$(".so-panels-welcome-message").show():this.$(".so-panels-welcome-message").hide()},activateContextMenu:function(e,t){var i=this,s=l(".siteorigin-panels-builder:visible").sort(function(e,t){return l(e).zIndex()>l(t).zIndex()?1:-1}).last(),o=l(".so-panels-dialog-wrapper:visible").sort(function(e,t){return l(e).zIndex()>l(t).zIndex()?1:-1}).last(),n=i.$el.closest(".so-panels-dialog-wrapper");if(i.$el.is(s)&&(0===o.length||o.is(n))){var a=l([]).add(i.$(".so-panels-welcome-message:visible")).add(i.$(".so-rows-container > .so-row-container")).add(i.$(".so-cells > .cell")).add(i.$(".cell-wrapper > .so-widget")).filter(function(i){return t.isOverEl(l(this),e)}),r=a.last().data("view");void 0!==r&&void 0!==r.buildContextualMenu?r.buildContextualMenu(e,t):a.last().hasClass("so-panels-welcome-message")&&this.buildContextualMenu(e,t)}},buildContextualMenu:function(e,t){var i={};this.supports("addRow")&&(i.add_row={title:panelsOptions.loc.contextual.add_row}),s.helpers.clipboard.canCopyPaste()&&s.helpers.clipboard.isModel("row-model")&&this.supports("addRow")&&(i.paste_row={title:panelsOptions.loc.contextual.row_paste}),_.isEmpty(i)||t.addSection("builder-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},i,function(e){switch(e){case"add_row":this.displayAddRowDialog();break;case"paste_row":this.pasteRowHandler()}}.bind(this))}})},{}],24:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-cell").html())),events:{"click .cell-wrapper":"handleCellClick"},row:null,widgetSortable:null,initialize:function(){this.model.get("widgets").on("add",this.onAddWidget,this)},render:function(){var e={weight:this.model.get("weight"),totalWeight:this.row.model.get("cells").totalWeight()};this.setElement(this.template(e)),this.$el.data("view",this);var t=this;return this.model.get("widgets").each(function(e){var i=new s.view.widget({model:e});i.cell=t,i.render(),i.$el.appendTo(t.$(".widgets-container"))}),this.initSortable(),this.initResizable(),this},initSortable:function(){if(!this.row.builder.supports("moveWidget"))return this;var e=this,t=e.row.builder.$el.attr("id");return this.widgetSortable=this.$(".widgets-container").sortable({placeholder:"so-widget-sortable-highlight",connectWith:"#"+t+" .so-cells .cell .widgets-container",tolerance:"pointer",scroll:!1,over:function(t,i){e.row.builder.trigger("widget_sortable_move")},stop:function(t,i){e.row.builder.addHistoryEntry("widget_moved");var s=l(i.item),o=s.data("view"),n=s.closest(".cell").data("view");o.model.moveToCell(n.model,{},s.index()),o.cell=n,o.cell.row.builder.model.refreshPanelsData()},helper:function(e,t){var i=t.clone().css({width:t.outerWidth(),"z-index":1e4,position:"fixed"}).addClass("widget-being-dragged").appendTo("body");return t.outerWidth()>720&&i.animate({"margin-left":e.pageX-t.offset().left-240,width:480},"fast"),i}}),this},refreshSortable:function(){_.isNull(this.widgetSortable)||this.widgetSortable.sortable("refresh")},initResizable:function(){if(!this.row.builder.supports("editRow"))return this;var e,t=this.$(".resize-handle").css("position","absolute"),i=this.row.$el,s=this;return t.draggable({axis:"x",containment:i,start:function(t,i){if(e=s.$el.prev().data("view"),!_.isUndefined(e)){var o=s.$el.clone().appendTo(i.helper).css({position:"absolute",top:"0",width:s.$el.outerWidth(),left:5,height:s.$el.outerHeight()});o.find(".resize-handle").remove();var n=e.$el.clone().appendTo(i.helper).css({position:"absolute",top:"0",width:e.$el.outerWidth(),right:5,height:e.$el.outerHeight()});n.find(".resize-handle").remove(),l(this).data({newCellClone:o,prevCellClone:n})}},drag:function(i,o){var n=s.row.$el.width()+10,a=s.model.get("weight")-(o.position.left+t.outerWidth()/2)/n,r=e.model.get("weight")+(o.position.left+t.outerWidth()/2)/n;l(this).data("newCellClone").css("width",n*a).find(".preview-cell-weight").html(Math.round(1e3*a)/10),l(this).data("prevCellClone").css("width",n*r).find(".preview-cell-weight").html(Math.round(1e3*r)/10)},stop:function(i,o){l(this).data("newCellClone").remove(),l(this).data("prevCellClone").remove();var n=s.row.$el.width()+10,a=s.model.get("weight")-(o.position.left+t.outerWidth()/2)/n,r=e.model.get("weight")+(o.position.left+t.outerWidth()/2)/n;a>.02&&r>.02&&(s.row.builder.addHistoryEntry("cell_resized"),s.model.set("weight",a),e.model.set("weight",r),s.row.resize()),o.helper.css("left",-t.outerWidth()/2),s.row.builder.model.refreshPanelsData()}}),this},onAddWidget:function(e,t,i){i=_.extend({noAnimate:!1},i);var l=new s.view.widget({model:e});l.cell=this,_.isUndefined(e.isDuplicate)&&(e.isDuplicate=!1),l.render({loadForm:e.isDuplicate}),_.isUndefined(i.at)||t.length<=1?l.$el.appendTo(this.$(".widgets-container")):l.$el.insertAfter(this.$(".widgets-container .so-widget").eq(i.at-1)),!1===i.noAnimate&&l.visualCreate(),this.refreshSortable(),this.row.resize()},handleCellClick:function(e){this.row.builder.$el.find(".so-cells .cell").removeClass("cell-selected"),this.row.builder.activeCell!==this||this.model.get("widgets").length?(this.$el.addClass("cell-selected"),this.row.builder.activeCell=this):this.row.builder.activeCell=null},pasteHandler:function(){var e=s.helpers.clipboard.getModel("widget-model");!_.isEmpty(e)&&e instanceof s.model.widget&&(this.row.builder.addHistoryEntry("widget_pasted"),e.cell=this.model,this.model.get("widgets").add(e),this.row.builder.model.refreshPanelsData())},buildContextualMenu:function(e,t){var i=this;t.hasSection("add-widget-below")||t.addSection("add-widget-cell",{sectionTitle:panelsOptions.loc.contextual.add_widget_cell,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){i.row.builder.addHistoryEntry("widget_added");var t=new s.model.widget({class:e});t.cell=i.model,t.cell.get("widgets").add(t),i.row.builder.model.refreshPanelsData()});var l={};this.row.builder.supports("addWidget")&&s.helpers.clipboard.isModel("widget-model")&&(l.paste={title:panelsOptions.loc.contextual.cell_paste_widget}),_.isEmpty(l)||t.addSection("cell-actions",{sectionTitle:panelsOptions.loc.contextual.cell_actions,search:!1},l,function(e){switch(e){case"paste":this.pasteHandler()}this.row.builder.model.refreshPanelsData()}.bind(this)),this.row.buildContextualMenu(e,t)}})},{}],25:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({dialogTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog").html())),dialogTabTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-tab").html())),tabbed:!1,rendered:!1,builder:!1,className:"so-panels-dialog-wrapper",dialogClass:"",dialogIcon:"",parentDialog:!1,dialogOpen:!1,editableLabel:!1,events:{"click .so-close":"closeDialog","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext"},initialize:function(){this.once("open_dialog",this.render),this.once("open_dialog",this.attach),this.once("open_dialog",this.setDialogClass),this.trigger("initialize_dialog",this),_.isUndefined(this.initializeDialog)||this.initializeDialog()},getNextDialog:function(){return null},getPrevDialog:function(){return null},setDialogClass:function(){""!==this.dialogClass&&this.$(".so-panels-dialog").addClass(this.dialogClass)},setBuilder:function(e){return this.builder=e,e.trigger("add_dialog",this,this.builder),this},attach:function(){return this.$el.appendTo("body"),this},parseDialogContent:function(e,t){t=_.extend({cid:this.cid},t);var i=l(_.template(s.helpers.utils.processTemplate(e))(t)),o={title:i.find(".title").html(),buttons:i.find(".buttons").html(),content:i.find(".content").html()};return i.has(".left-sidebar")&&(o.left_sidebar=i.find(".left-sidebar").html()),i.has(".right-sidebar")&&(o.right_sidebar=i.find(".right-sidebar").html()),o},renderDialog:function(e){if(e=_.extend({editableLabel:this.editableLabel,dialogIcon:this.dialogIcon},e),this.$el.html(this.dialogTemplate(e)).hide(),this.$el.data("view",this),this.$el.addClass("so-panels-dialog-wrapper"),!1!==this.parentDialog){var t=this,i=l('<h3 class="so-parent-link"></h3>').html(this.parentDialog.text+'<div class="so-separator"></div>');i.click(function(e){e.preventDefault(),t.closeDialog(),t.parentDialog.openDialog()}),this.$(".so-title-bar").prepend(i)}return this.$(".so-title-bar .so-title-editable").length&&this.initEditableLabel(),this},initTabs:function(){var e=this.$(".so-sidebar-tabs li a");if(0===e.length)return this;var t=this;return e.click(function(e){e.preventDefault();var i=l(this);t.$(".so-sidebar-tabs li").removeClass("tab-active"),t.$(".so-content .so-content-tabs > *").hide(),i.parent().addClass("tab-active");var s=i.attr("href");if(!_.isUndefined(s)&&"#"===s.charAt(0)){var o=s.split("#")[1];t.$(".so-content .so-content-tabs .tab-"+o).show()}t.trigger("tab_click",i)}),this.$(".so-sidebar-tabs li a").first().click(),this},initToolbar:function(){this.$(".so-toolbar .so-buttons .so-toolbar-button").click(function(e){e.preventDefault(),this.trigger("button_click",l(e.currentTarget))}.bind(this)),this.$(".so-toolbar .so-buttons .so-dropdown-button").click(function(e){e.preventDefault();var t=l(e.currentTarget),i=t.siblings(".so-dropdown-links-wrapper");i.is(".hidden")?i.removeClass("hidden"):i.addClass("hidden")}.bind(this)),l("html").click(function(e){this.$(".so-dropdown-links-wrapper").not(".hidden").each(function(t,i){var s=l(i),o=l(e.target);0!==o.length&&(o.is(".so-needs-confirm")&&!o.is(".so-confirmed")||o.is(".so-dropdown-button"))||s.addClass("hidden")})}.bind(this))},initEditableLabel:function(){var e=this.$(".so-title-bar .so-title-editable");e.keypress(function(t){var i="keypress"===t.type&&13===t.keyCode;if(i){var s=l(":tabbable"),o=s.index(e);s.eq(o+1).focus(),window.getSelection().removeAllRanges()}return!i}).blur(function(){var t=e.text().replace(/^\s+|\s+$/gm,"");t!==e.data("original-value").replace(/^\s+|\s+$/gm,"")&&(e.text(t),this.trigger("edit_label",t))}.bind(this)),e.focus(function(){e.data("original-value",e.text()),s.helpers.utils.selectElementContents(this)})},setupDialog:function(){this.openDialog(),this.closeDialog()},refreshDialogNav:function(){this.$(".so-title-bar .so-nav").show().removeClass("so-disabled");var e=this.getNextDialog(),t=this.$(".so-title-bar .so-next"),i=this.getPrevDialog(),s=this.$(".so-title-bar .so-previous");null===e?t.hide():!1===e&&t.addClass("so-disabled"),null===i?s.hide():!1===i&&s.addClass("so-disabled")},openDialog:function(e){e=_.extend({silent:!1},e),e.silent||this.trigger("open_dialog"),this.dialogOpen=!0,this.refreshDialogNav(),s.helpers.pageScroll.lock(),l(window).on("keyup",this.keyboardListen),this.$el.show(),e.silent||(this.trigger("open_dialog_complete"),this.builder.trigger("open_dialog",this),l(document).trigger("open_dialog",this))},closeDialog:function(e){e=_.extend({silent:!1},e),e.silent||this.trigger("close_dialog"),this.dialogOpen=!1,this.$el.hide(),s.helpers.pageScroll.unlock(),l(window).off("keyup",this.keyboardListen),e.silent||(this.trigger("close_dialog_complete"),this.builder.trigger("close_dialog",this))},keyboardListen:function(e){27===e.which&&l(".so-panels-dialog-wrapper .so-close").trigger("click")},navToPrevious:function(){this.closeDialog();var e=this.getPrevDialog();null!==e&&!1!==e&&e.openDialog()},navToNext:function(){this.closeDialog();var e=this.getNextDialog();null!==e&&!1!==e&&e.openDialog()},getFormValues:function(e){_.isUndefined(e)&&(e=".so-content");var t,i=this.$(e),s={};return i.find("[name]").each(function(){var e=l(this);try{var i=/([A-Za-z_]+)\[(.*)\]/.exec(e.attr("name"));if(_.isEmpty(i))return!0;_.isUndefined(i[2])?t=e.attr("name"):(t=i[2].split("]["),t.unshift(i[1])),t=t.map(function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e});var o=s,n=null,a=!!_.isString(e.attr("type"))&&e.attr("type").toLowerCase();if("checkbox"===a)n=e.is(":checked")?""===e.val()||e.val():null;else if("radio"===a){if(!e.is(":checked"))return;n=e.val()}else if("TEXTAREA"===e.prop("tagName")&&e.hasClass("wp-editor-area")){var r=null;"undefined"!=typeof tinyMCE&&(r=tinyMCE.get(e.attr("id"))),n=null!==r&&_.isFunction(r.getContent)&&!r.isHidden()?r.getContent():e.val()}else if("SELECT"===e.prop("tagName")){var d=e.find("option:selected");1===d.length?n=e.find("option:selected").val():d.length>1&&(n=_.map(e.find("option:selected"),function(e,t){return l(e).val()}))}else n=e.val();if(!_.isUndefined(e.data("panels-filter")))switch(e.data("panels-filter")){case"json_parse":try{n=JSON.parse(n)}catch(e){n=""}}if(null!==n)for(var c=0;c<t.length;c++)c===t.length-1?""===t[c]?o.push(n):o[t[c]]=n:(_.isUndefined(o[t[c]])&&(""===t[c+1]?o[t[c]]=[]:o[t[c]]={}),o=o[t[c]])}catch(t){console.log("Field ["+e.attr("name")+"] could not be processed and was skipped - "+t.message)}}),s},setStatusMessage:function(e,t,i){var s=i?'<span class="dashicons dashicons-warning"></span>'+e:e;this.$(".so-toolbar .so-status").html(s),!_.isUndefined(t)&&t?this.$(".so-toolbar .so-status").addClass("so-panels-loading"):this.$(".so-toolbar .so-status").removeClass("so-panels-loading")},setParent:function(e,t){this.parentDialog={text:e,dialog:t}}})},{}],26:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-live-editor").html())),previewScrollTop:0,loadTimes:[],previewFrameId:1,previewUrl:null,previewIframe:null,events:{"click .live-editor-close":"close","click .live-editor-collapse":"collapse","click .live-editor-mode":"mobileToggle"},initialize:function(e){e=_.extend({builder:!1,previewUrl:!1},e),_.isEmpty(e.previewUrl)&&(e.previewUrl=panelsOptions.ajaxurl+"&action=so_panels_live_editor_preview"),this.builder=e.builder,this.previewUrl=e.previewUrl,this.builder.model.on("refresh_panels_data",this.handleRefreshData,this),this.builder.model.on("load_panels_data",this.handleLoadData,this)},render:function(){this.setElement(this.template()),this.$el.hide();var e=this,t=!1;return l(document).mousedown(function(){t=!0}).mouseup(function(){t=!1}),this.$el.on("mouseenter",".so-widget-wrapper",function(){var i=l(this),s=i.data("live-editor-preview-widget");t||void 0===s||!s.length||e.$(".so-preview-overlay").is(":visible")||(e.highlightElement(s),e.scrollToElement(s))}),e.$el.on("mouseleave",".so-widget-wrapper",function(){e.resetHighlights()}),e.builder.on("open_dialog",function(){e.resetHighlights()}),this},attach:function(){this.$el.appendTo("body")},open:function(){if(""===this.$el.html()&&this.render(),0===this.$el.closest("body").length&&this.attach(),s.helpers.pageScroll.lock(),this.$el.is(":visible"))return this;if(this.$el.show(),this.refreshPreview(this.builder.model.getPanelsData()),this.originalContainer=this.builder.$el.parent(),this.builder.$el.appendTo(this.$(".so-live-editor-builder")),this.builder.$(".so-tool-button.so-live-editor").hide(),this.builder.trigger("builder_resize"),"auto-draft"===l("#original_post_status").val()&&!this.autoSaved){var e=this;wp.autosave&&(""===l('#title[name="post_title"]').val()&&l('#title[name="post_title"]').val(panelsOptions.loc.draft).trigger("keydown"),l(document).one("heartbeat-tick.autosave",function(){e.autoSaved=!0,e.refreshPreview(e.builder.model.getPanelsData())}),wp.autosave.server.triggerSave())}},close:function(){if(!this.$el.is(":visible"))return this;this.$el.hide(),s.helpers.pageScroll.unlock(),this.builder.$el.appendTo(this.originalContainer),this.builder.$(".so-tool-button.so-live-editor").show(),this.builder.trigger("builder_resize")},collapse:function(){this.$el.toggleClass("so-collapsed");var e=this.$(".live-editor-collapse span");e.html(e.data(this.$el.hasClass("so-collapsed")?"expand":"collapse"))},highlightElement:function(e){_.isUndefined(this.resetHighlightTimeout)||clearTimeout(this.resetHighlightTimeout),this.previewIframe.contents().find("body").find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return 0===l(this).parents(".so-panel").length}).not(e).addClass("so-panels-faded"),e.removeClass("so-panels-faded").addClass("so-panels-highlighted")},resetHighlights:function(){var e=this.previewIframe.contents().find("body");this.resetHighlightTimeout=setTimeout(function(){e.find(".panel-grid .panel-grid-cell .so-panel").removeClass("so-panels-faded so-panels-highlighted")},100)},scrollToElement:function(e){this.$(".so-preview iframe")[0].contentWindow.liveEditorScrollTo(e)},handleRefreshData:function(e,t){if(!this.$el.is(":visible"))return this;this.refreshPreview(e)},handleLoadData:function(){if(!this.$el.is(":visible"))return this;this.refreshPreview(this.builder.model.getPanelsData())},refreshPreview:function(e){var t=this.loadTimes.length?_.reduce(this.loadTimes,function(e,t){return e+t},0)/this.loadTimes.length:1e3;_.isNull(this.previewIframe)||this.$(".so-preview-overlay").is(":visible")||(this.previewScrollTop=this.previewIframe.contents().scrollTop()),this.$(".so-preview-overlay").show(),this.$(".so-preview-overlay .so-loading-bar").clearQueue().css("width","0%").animate({width:"100%"},parseInt(t)+100),this.postToIframe({live_editor_panels_data:JSON.stringify(e),live_editor_post_ID:this.builder.config.postId},this.previewUrl,this.$(".so-preview")),this.previewIframe.data("load-start",(new Date).getTime())},postToIframe:function(e,t,i){_.isNull(this.previewIframe)||this.previewIframe.remove();var s="siteorigin-panels-live-preview-"+this.previewFrameId;this.previewIframe=l('<iframe src="javascript:false;" />').attr({id:s,name:s}).appendTo(i),this.setupPreviewFrame(this.previewIframe);var o=l('<form id="soPostToPreviewFrame" method="post" />').attr({id:s,target:this.previewIframe.attr("id"),action:t}).appendTo("body");return l.each(e,function(e,t){l('<input type="hidden" />').attr({name:e,value:t}).appendTo(o)}),o.submit().remove(),this.previewFrameId++,this.previewIframe},setupPreviewFrame:function(e){var t=this;e.data("iframeready",!1).on("iframeready",function(){var e=l(this),i=e.contents();if(!e.data("iframeready")){e.data("iframeready",!0),void 0!==e.data("load-start")&&(t.loadTimes.unshift((new Date).getTime()-e.data("load-start")),_.isEmpty(t.loadTimes)||(t.loadTimes=t.loadTimes.slice(0,4))),setTimeout(function(){i.scrollTop(t.previewScrollTop),t.$(".so-preview-overlay").hide()},100);var s=i.find("#pl-"+t.builder.config.postId);s.find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return l(this).closest(".panel-layout").is(s)}).each(function(e,i){var s=l(i),o=t.$(".so-live-editor-builder .so-widget-wrapper").eq(s.data("index"));o.data("live-editor-preview-widget",s),s.css({cursor:"pointer"}).mouseenter(function(){o.parent().addClass("so-hovered"),t.highlightElement(s)}).mouseleave(function(){o.parent().removeClass("so-hovered"),t.resetHighlights()}).click(function(e){e.preventDefault(),o.find(".title h4").click()})}),i.find("a").css({"pointer-events":"none"}).click(function(e){e.preventDefault()})}}).on("load",function(){var e=l(this);e.data("iframeready")||e.trigger("iframeready")})},hasPreviewUrl:function(){return""!==this.$("form.live-editor-form").attr("action")},mobileToggle:function(e){var t=l(e.currentTarget);this.$(".live-editor-mode").not(t).removeClass("so-active"),t.addClass("so-active"),this.$el.removeClass("live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode").addClass("live-editor-"+t.data("mode")+"-mode")}})},{}],27:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-row").html())),events:{"click .so-row-settings":"editSettingsHandler","click .so-row-duplicate":"duplicateHandler","click .so-row-delete":"confirmedDeleteHandler","click .so-row-color":"rowColorChangeHandler"},builder:null,dialog:null,initialize:function(){var e=this.model.get("cells");e.on("add",this.handleCellAdd,this),e.on("remove",this.handleCellRemove,this),this.model.on("reweight_cells",this.resize,this),this.model.on("destroy",this.onModelDestroy,this),this.model.on("visual_destroy",this.visualDestroyModel,this);var t=this;e.each(function(e){t.listenTo(e.get("widgets"),"add",t.resize)}),e.on("add",function(e){t.listenTo(e.get("widgets"),"add",t.resize)},this),this.model.on("change:label",this.onLabelChange,this)},render:function(){var e=this.model.has("color_label")?this.model.get("color_label"):1,t=this.model.has("label")?this.model.get("label"):"";this.setElement(this.template({rowColorLabel:e,rowLabel:t})),this.$el.data("view",this);var i=this;return this.model.get("cells").each(function(e){var t=new s.view.cell({model:e});t.row=i,t.render(),t.$el.appendTo(i.$(".so-cells"))}),this.builder.supports("rowAction")?(this.builder.supports("editRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-settings").parent().remove(),this.$el.addClass("so-row-no-edit")),this.builder.supports("addRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate").parent().remove(),this.$el.addClass("so-row-no-duplicate")),this.builder.supports("deleteRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-delete").parent().remove(),this.$el.addClass("so-row-no-delete"))):(this.$(".so-row-toolbar .so-dropdown-wrapper").remove(),this.$el.addClass("so-row-no-actions")),this.builder.supports("moveRow")||(this.$(".so-row-toolbar .so-row-move").remove(),this.$el.addClass("so-row-no-move")),l.trim(this.$(".so-row-toolbar").html()).length||this.$(".so-row-toolbar").remove(),this.builder.on("widget_sortable_move",this.resize,this),this.builder.on("builder_resize",this.resize,this),this.resize(),this},visualCreate:function(){this.$el.hide().fadeIn("fast")},resize:function(e){if(this.$el.is(":visible")){this.$(".so-cells .cell-wrapper").css("min-height",0),this.$(".so-cells .resize-handle").css("height",0);var t=0;this.$(".so-cells .cell").each(function(){t=Math.max(t,l(this).height()),l(this).css("width",100*l(this).data("view").model.get("weight")+"%")}),this.$(".so-cells .cell-wrapper").css("min-height",Math.max(t,63)),this.$(".so-cells .resize-handle").css("height",this.$(".so-cells .cell-wrapper").outerHeight())}},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){this.builder.addHistoryEntry("row_deleted");var e=this;this.$el.fadeOut("normal",function(){e.model.destroy(),e.builder.model.refreshPanelsData()})},onLabelChange:function(e,t){0==this.$(".so-row-label").length?this.$(".so-row-toolbar").prepend('<h3 class="so-row-label">'+t+"</h3>"):this.$(".so-row-label").text(t)},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()},copyHandler:function(){s.helpers.clipboard.setModel(this.model)},pasteHandler:function(){var e=s.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof s.model.row&&(this.builder.addHistoryEntry("row_pasted"),e.builder=this.builder.model,this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData())},confirmedDeleteHandler:function(e){var t=l(e.target);if(t.hasClass("dashicons")&&(t=l.parent()),t.hasClass("so-confirmed"))this.visualDestroyModel();else{var i=t.html();t.addClass("so-confirmed").html('<span class="dashicons dashicons-yes"></span>'+panelsOptions.loc.dropdown_confirm),setTimeout(function(){t.removeClass("so-confirmed").html(i)},2500)}},editSettingsHandler:function(){if(this.builder.supports("editRow"))return null===this.dialog&&(this.dialog=new s.dialog.row,this.dialog.setBuilder(this.builder).setRowModel(this.model)),this.dialog.openDialog(),this},deleteHandler:function(){return this.model.destroy(),this},rowColorChangeHandler:function(e){this.$(".so-row-color").removeClass("so-row-color-selected");var t=l(e.target),i=t.data("color-label"),s=this.model.has("color_label")?this.model.get("color_label"):1;t.addClass("so-row-color-selected"),this.$el.removeClass("so-row-color-"+s),this.$el.addClass("so-row-color-"+i),this.model.set("color_label",i)},handleCellAdd:function(e){var t=new s.view.cell({model:e});t.row=this,t.render(),t.$el.appendTo(this.$(".so-cells"))},handleCellRemove:function(e){this.$(".so-cells > .cell").each(function(){var t=l(this).data("view");_.isUndefined(t)||t.model.cid===e.cid&&t.remove()})},buildContextualMenu:function(e,t){for(var i=[],l=1;l<5;l++)i.push({title:l+" "+panelsOptions.loc.contextual.column});this.builder.supports("addRow")&&t.addSection("add-row",{sectionTitle:panelsOptions.loc.contextual.add_row,search:!1},i,function(e){this.builder.addHistoryEntry("row_added");for(var t=Number(e)+1,i=[],l=0;l<t;l++)i.push({weight:100/t});var o=new s.model.row({collection:this.collection}),n=new s.collection.cells(i);n.each(function(e){e.row=o}),o.setCells(n),o.builder=this.builder.model,this.builder.model.get("rows").add(o,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()}.bind(this));var o={};this.builder.supports("editRow")&&(o.edit={title:panelsOptions.loc.contextual.row_edit}),s.helpers.clipboard.canCopyPaste()&&(o.copy={title:panelsOptions.loc.contextual.row_copy},this.builder.supports("addRow")&&s.helpers.clipboard.isModel("row-model")&&(o.paste={title:panelsOptions.loc.contextual.row_paste})),this.builder.supports("addRow")&&(o.duplicate={title:panelsOptions.loc.contextual.row_duplicate}),this.builder.supports("deleteRow")&&(o.delete={title:panelsOptions.loc.contextual.row_delete,confirm:!0}),_.isEmpty(o)||t.addSection("row-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},o,function(e){switch(e){case"edit":this.editSettingsHandler();break;case"copy":this.copyHandler();break;case"paste":this.pasteHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this))}})},{}],28:[function(e,t,i){var s=(window.panels,jQuery);t.exports=Backbone.View.extend({stylesLoaded:!1,initialize:function(){},render:function(e,t,i){if(!_.isUndefined(e)){i=_.extend({builderType:"",dialog:null},i),this.$el.addClass("so-visual-styles so-"+e+"-styles");var l={builderType:i.builderType};return"cell"===e&&(l.index=i.index),s.post(panelsOptions.ajaxurl,{action:"so_panels_style_form",type:e,style:this.model.get("style"),args:JSON.stringify(l),postId:t},function(e){this.$el.html(e),this.setupFields(),this.stylesLoaded=!0,this.trigger("styles_loaded",!_.isEmpty(e)),_.isNull(i.dialog)||i.dialog.trigger("styles_loaded",!_.isEmpty(e))}.bind(this)),this}},attach:function(e){e.append(this.$el)},detach:function(){this.$el.detach()},setupFields:function(){this.$(".style-section-wrapper").each(function(){var e=s(this);e.find(".style-section-head").click(function(t){t.preventDefault(),e.find(".style-section-fields").slideToggle("fast")})}),_.isUndefined(s.fn.wpColorPicker)||(_.isObject(panelsOptions.wpColorPickerOptions.palettes)&&!s.isArray(panelsOptions.wpColorPickerOptions.palettes)&&(panelsOptions.wpColorPickerOptions.palettes=s.map(panelsOptions.wpColorPickerOptions.palettes,function(e){return e})),this.$(".so-wp-color-field").wpColorPicker(panelsOptions.wpColorPickerOptions)),this.$(".style-field-image").each(function(){var e=null,t=s(this);t.find(".so-image-selector").click(function(i){i.preventDefault(),null===e&&(e=wp.media({title:"choose",library:{type:"image"},button:{text:"Done",close:!0}}),e.on("select",function(){var i=e.state().get("selection").first().attributes,s=i.url;if(!_.isUndefined(i.sizes))try{s=i.sizes.thumbnail.url}catch(e){s=i.sizes.full.url}t.find(".current-image").css("background-image","url("+s+")"),t.find("input").val(i.id)})),e.open()}),t.find(".remove-image").click(function(e){e.preventDefault(),t.find(".current-image").css("background-image","none"),t.find("input").val("")})}),this.$(".style-field-measurement").each(function(){var e=s(this),t=e.find('input[type="text"]'),i=e.find("select"),l=e.find('input[type="hidden"]');t.focus(function(){s(this).select()});!function(e){if(""!==e){
4
- var o=/(?:([0-9\.,\-]+)(.*))+/,n=l.val().split(" "),a=[];for(var r in n){var d=o.exec(n[r]);_.isNull(d)||_.isUndefined(d[1])||_.isUndefined(d[2])||(a.push(d[1]),i.val(d[2]))}1===t.length?t.val(a.join(" ")):(1===a.length?a=[a[0],a[0],a[0],a[0]]:2===a.length?a=[a[0],a[1],a[0],a[1]]:3===a.length&&(a=[a[0],a[1],a[2],a[1]]),t.each(function(e,t){s(t).val(a[e])}))}}(l.val());var o=function(e){if(1===t.length){var o=t.val().split(" ").filter(function(e){return""!==e}).map(function(e){return e+i.val()}).join(" ");l.val(o)}else{var n=s(e.target),a=[],r=[],d=[];t.each(function(e,t){var i=""!==s(t).val()?parseFloat(s(t).val()):null;a.push(i),null===i?r.push(e):d.push(e)}),3===r.length&&d[0]===t.index(n)&&(t.val(n.val()),a=[n.val(),n.val(),n.val(),n.val()]),JSON.stringify(a)===JSON.stringify([null,null,null,null])?l.val(""):l.val(a.map(function(e){return(null===e?0:e)+i.val()}).join(" "))}};t.change(o),i.change(o)})}})},{}],29:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-widget").html())),cell:null,dialog:null,events:{"click .widget-edit":"editHandler","click .title h4":"titleClickHandler","click .actions .widget-duplicate":"duplicateHandler","click .actions .widget-delete":"deleteHandler"},initialize:function(){this.model.on("user_edit",this.editHandler,this),this.model.on("user_duplicate",this.duplicateHandler,this),this.model.on("destroy",this.onModelDestroy,this),this.model.on("visual_destroy",this.visualDestroyModel,this),this.model.on("change:values",this.onModelChange,this),this.model.on("change:label",this.onLabelChange,this)},render:function(e){if(e=_.extend({loadForm:!1},e),this.setElement(this.template({title:this.model.getWidgetField("title"),description:this.model.getTitle()})),this.$el.data("view",this),this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")||(this.$(".actions .widget-edit").remove(),this.$el.addClass("so-widget-no-edit")),this.cell.row.builder.supports("addWidget")||(this.$(".actions .widget-duplicate").remove(),this.$el.addClass("so-widget-no-duplicate")),this.cell.row.builder.supports("deleteWidget")||(this.$(".actions .widget-delete").remove(),this.$el.addClass("so-widget-no-delete")),this.cell.row.builder.supports("moveWidget")||this.$el.addClass("so-widget-no-move"),l.trim(this.$(".actions").html()).length||this.$(".actions").remove(),this.model.get("read_only")&&this.$el.addClass("so-widget-read-only"),0===_.size(this.model.get("values"))||e.loadForm){var t=this.getEditDialog();t.once("form_loaded",t.saveWidget,t),t.setupDialog()}return this},visualCreate:function(){this.$el.hide().fadeIn("fast")},getEditDialog:function(){return null===this.dialog&&(this.dialog=new s.dialog.widget({model:this.model}),this.dialog.setBuilder(this.cell.row.builder),this.dialog.widgetView=this),this.dialog},editHandler:function(){this.getEditDialog().openDialog()},titleClickHandler:function(e){return!this.cell.row.builder.supports("editWidget")||this.model.get("read_only")?this:(this.editHandler(),this)},duplicateHandler:function(){this.cell.row.builder.addHistoryEntry("widget_duplicated");var e=this.model.clone(this.model.cell);return this.cell.model.get("widgets").add(e,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData(),this},copyHandler:function(){s.helpers.clipboard.setModel(this.model)},deleteHandler:function(){return this.model.trigger("visual_destroy"),this},onModelChange:function(){this.$(".description").html(this.model.getTitle())},onLabelChange:function(e){this.$(".title > h4").text(e.getWidgetField("title"))},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){this.cell.row.builder.addHistoryEntry("widget_deleted");var e=this;return this.$el.fadeOut("fast",function(){e.cell.row.resize(),e.model.destroy(),e.cell.row.builder.model.refreshPanelsData(),e.remove()}),this},buildContextualMenu:function(e,t){this.cell.row.builder.supports("addWidget")&&t.addSection("add-widget-below",{sectionTitle:panelsOptions.loc.contextual.add_widget_below,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){this.cell.row.builder.addHistoryEntry("widget_added");var t=new s.model.widget({class:e});t.cell=this.cell.model,this.cell.model.get("widgets").add(t,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData()}.bind(this));var i={};this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")&&(i.edit={title:panelsOptions.loc.contextual.widget_edit}),s.helpers.clipboard.canCopyPaste()&&(i.copy={title:panelsOptions.loc.contextual.widget_copy}),this.cell.row.builder.supports("addWidget")&&(i.duplicate={title:panelsOptions.loc.contextual.widget_duplicate}),this.cell.row.builder.supports("deleteWidget")&&(i.delete={title:panelsOptions.loc.contextual.widget_delete,confirm:!0}),_.isEmpty(i)||t.addSection("widget-actions",{sectionTitle:panelsOptions.loc.contextual.widget_actions,search:!1},i,function(e){switch(e){case"edit":this.editHandler();break;case"copy":this.copyHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this)),this.cell.buildContextualMenu(e,t)}})},{}],30:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.customHtmlWidgets,o=s("<div></div>"),n=t.find(".widget-content:first");n.before(o);var a=new l.CustomHtmlWidgetControl({el:o,syncContainer:n});return a.initializeEditor(),a.editor.codemirror.refresh(),a}};t.exports=l},{}],31:[function(e,t,i){var s=e("./custom-html-widget"),l=e("./media-widget"),o=e("./text-widget"),n={CUSTOM_HTML:"custom_html",MEDIA_AUDIO:"media_audio",MEDIA_GALLERY:"media_gallery",MEDIA_IMAGE:"media_image",MEDIA_VIDEO:"media_video",TEXT:"text",addWidget:function(e,t){var i,n=e.find("> .id_base").val();switch(n){case this.CUSTOM_HTML:i=s;break;case this.MEDIA_AUDIO:case this.MEDIA_GALLERY:case this.MEDIA_IMAGE:case this.MEDIA_VIDEO:i=l;break;case this.TEXT:i=o}i.addWidget(n,e,t)}};t.exports=n},{"./custom-html-widget":30,"./media-widget":32,"./text-widget":33}],32:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.mediaWidgets,o=l.controlConstructors[e];if(o){var n=l.modelConstructors[e]||l.MediaWidgetModel,a=t.find("> .widget-content"),r=s('<div class="media-widget-control"></div>');a.before(r);var d={};a.find(".media-widget-instance-property").each(function(){var e=s(this);d[e.data("property")]=e.val()}),d.widget_id=i;var c=new n(d),h=new o({el:r,syncContainer:a,model:c});return h.render(),h}}};t.exports=l},{}],33:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.textWidgets,o={},n=t.find(".visual");if(n.length>0){if(!n.val())return null;var a=s("<div></div>"),r=t.find(".widget-content:first");r.before(a),o={el:a,syncContainer:r}}else o={el:t};var d=new l.TextWidgetControl(o);return d.initializeEditor(),d}};t.exports=l},{}]},{},[16]);
1
  !function e(t,i,s){function l(n,a){if(!i[n]){if(!t[n]){var r="function"==typeof require&&require;if(!a&&r)return r(n,!0);if(o)return o(n,!0);var d=new Error("Cannot find module '"+n+"'");throw d.code="MODULE_NOT_FOUND",d}var c=i[n]={exports:{}};t[n][0].call(c.exports,function(e){var i=t[n][1][e];return l(i||e)},c,c.exports,e,t,i,s)}return i[n].exports}for(var o="function"==typeof require&&require,n=0;n<s.length;n++)l(s[n]);return l}({1:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.cell,initialize:function(){},totalWeight:function(){var e=0;return this.each(function(t){e+=t.get("weight")}),e}})},{}],2:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.historyEntry,builder:null,maxSize:12,initialize:function(){this.on("add",this.onAddEntry,this)},addEntry:function(e,t){_.isEmpty(t)&&(t=this.builder.getPanelsData());var i=new s.model.historyEntry({text:e,data:JSON.stringify(t),time:parseInt((new Date).getTime()/1e3),collection:this});this.add(i)},onAddEntry:function(e){if(this.models.length>1){var t=this.at(this.models.length-2);(e.get("text")===t.get("text")&&e.get("time")-t.get("time")<15||e.get("data")===t.get("data"))&&(this.remove(e),t.set("count",t.get("count")+1))}for(;this.models.length>this.maxSize;)this.shift()}})},{}],3:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.row,empty:function(){for(var e;;){if(!(e=this.collection.first()))break;e.destroy()}}})},{}],4:[function(e,t,i){var s=window.panels;t.exports=Backbone.Collection.extend({model:s.model.widget,initialize:function(){}})},{}],5:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({dialogClass:"so-panels-dialog-add-builder",render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-builder").html(),{})),this.$(".so-content .siteorigin-panels-builder").append(this.builder.$el)},initializeDialog:function(){var e=this;this.once("open_dialog_complete",function(){e.builder.initSortable()}),this.on("open_dialog_complete",function(){e.builder.trigger("builder_resize")})}})},{}],6:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({historyEntryTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-history-entry").html())),entries:{},currentEntry:null,revertEntry:null,selectedEntry:null,previewScrollTop:null,dialogClass:"so-panels-dialog-history",dialogIcon:"history",events:{"click .so-close":"closeDialog","click .so-restore":"restoreSelectedEntry"},initializeDialog:function(){this.entries=new s.collection.historyEntries,this.on("open_dialog",this.setCurrentEntry,this),this.on("open_dialog",this.renderHistoryEntries,this)},render:function(){var e=this;this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-history").html(),{})),this.$("iframe.siteorigin-panels-history-iframe").load(function(){var t=l(this);t.show(),t.contents().scrollTop(e.previewScrollTop)})},setRevertEntry:function(e){this.revertEntry=new s.model.historyEntry({data:JSON.stringify(e.getPanelsData()),time:parseInt((new Date).getTime()/1e3)})},setCurrentEntry:function(){this.currentEntry=new s.model.historyEntry({data:JSON.stringify(this.builder.model.getPanelsData()),time:parseInt((new Date).getTime()/1e3)}),this.selectedEntry=this.currentEntry,this.previewEntry(this.currentEntry),this.$(".so-buttons .so-restore").addClass("disabled")},renderHistoryEntries:function(){var e=this,t=this.$(".history-entries").empty();this.currentEntry.get("data")===this.revertEntry.get("data")&&_.isEmpty(this.entries.models)||l(this.historyEntryTemplate({title:panelsOptions.loc.history.revert,count:1})).data("historyEntry",this.revertEntry).prependTo(t),this.entries.each(function(i){var s=e.historyEntryTemplate({title:panelsOptions.loc.history[i.get("text")],count:i.get("count")});l(s).data("historyEntry",i).prependTo(t)}),l(this.historyEntryTemplate({title:panelsOptions.loc.history.current,count:1})).data("historyEntry",this.currentEntry).addClass("so-selected").prependTo(t),t.find(".history-entry").click(function(){var i=jQuery(this);t.find(".history-entry").not(i).removeClass("so-selected"),i.addClass("so-selected");var s=i.data("historyEntry");e.selectedEntry=s,e.selectedEntry.cid!==e.currentEntry.cid?e.$(".so-buttons .so-restore").removeClass("disabled"):e.$(".so-buttons .so-restore").addClass("disabled"),e.previewEntry(s)}),this.updateEntryTimes()},previewEntry:function(e){var t=this.$("iframe.siteorigin-panels-history-iframe");t.hide(),this.previewScrollTop=t.contents().scrollTop(),this.$('form.history-form input[name="live_editor_panels_data"]').val(e.get("data")),this.$('form.history-form input[name="live_editor_post_ID"]').val(this.builder.config.postId),this.$("form.history-form").submit()},restoreSelectedEntry:function(){return!this.$(".so-buttons .so-restore").hasClass("disabled")&&(this.currentEntry.get("data")===this.selectedEntry.get("data")?(this.closeDialog(),!1):("restore"!==this.selectedEntry.get("text")&&this.builder.addHistoryEntry("restore",this.builder.model.getPanelsData()),this.builder.model.loadPanelsData(JSON.parse(this.selectedEntry.get("data"))),this.closeDialog(),!1))},updateEntryTimes:function(){var e=this;this.$(".history-entries .history-entry").each(function(){var t=jQuery(this),i=t.find(".timesince"),s=t.data("historyEntry");i.html(e.timeSince(s.get("time")))})},timeSince:function(e){var t,i=parseInt((new Date).getTime()/1e3)-e,s=[];return i>3600&&(t=Math.floor(i/3600),1===t?s.push(panelsOptions.loc.time.hour.replace("%d",t)):s.push(panelsOptions.loc.time.hours.replace("%d",t)),i-=3600*t),i>60&&(t=Math.floor(i/60),1===t?s.push(panelsOptions.loc.time.minute.replace("%d",t)):s.push(panelsOptions.loc.time.minutes.replace("%d",t)),i-=60*t),i>0&&(1===i?s.push(panelsOptions.loc.time.second.replace("%d",i)):s.push(panelsOptions.loc.time.seconds.replace("%d",i))),_.isEmpty(s)?panelsOptions.loc.time.now:panelsOptions.loc.time.ago.replace("%s",s.slice(0,2).join(", "))}})},{}],7:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({directoryTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-directory-items").html())),builder:null,dialogClass:"so-panels-dialog-prebuilt-layouts",dialogIcon:"layouts",layoutCache:{},currentTab:!1,directoryPage:1,events:{"click .so-close":"closeDialog","click .so-sidebar-tabs li a":"tabClickHandler","click .so-content .layout":"layoutClickHandler","keyup .so-sidebar-search":"searchHandler","click .so-screenshot, .so-title":"directoryItemClickHandler"},initializeDialog:function(){var e=this;this.on("open_dialog",function(){e.$(".so-sidebar-tabs li a").first().click(),e.$(".so-status").removeClass("so-panels-loading")}),this.on("button_click",this.toolbarButtonClick,this)},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-prebuilt").html(),{})),this.initToolbar()},tabClickHandler:function(e){e.preventDefault(),this.selectedLayoutItem=null,this.uploadedLayout=null,this.updateButtonState(!1),this.$(".so-sidebar-tabs li").removeClass("tab-active");var t=l(e.target),i=t.attr("href").split("#")[1];t.parent().addClass("tab-active");var s=this;this.$(".so-content").empty(),s.currentTab=i,"import"==i?this.displayImportExport():this.displayLayoutDirectory("",1,i),s.$(".so-sidebar-search").val("")},displayImportExport:function(){var e=this.$(".so-content").empty().removeClass("so-panels-loading");e.html(l("#siteorigin-panels-dialog-prebuilt-importexport").html());var t=this,i=t.$(".import-upload-ui").hide();new plupload.Uploader({runtimes:"html5,silverlight,flash,html4",browse_button:i.find(".file-browse-button").get(0),container:i.get(0),drop_element:i.find(".drag-upload-area").get(0),file_data_name:"panels_import_data",multiple_queues:!1,max_file_size:panelsOptions.plupload.max_file_size,url:panelsOptions.plupload.url,flash_swf_url:panelsOptions.plupload.flash_swf_url,silverlight_xap_url:panelsOptions.plupload.silverlight_xap_url,filters:[{title:panelsOptions.plupload.filter_title,extensions:"json"}],multipart_params:{action:"so_panels_import_layout"},init:{PostInit:function(e){e.features.dragdrop&&i.addClass("has-drag-drop"),i.show().find(".progress-precent").css("width","0%")},FilesAdded:function(e){i.find(".file-browse-button").blur(),i.find(".drag-upload-area").removeClass("file-dragover"),i.find(".progress-bar").fadeIn("fast"),t.$(".js-so-selected-file").text(panelsOptions.loc.prebuilt_loading),e.start()},UploadProgress:function(e,t){i.find(".progress-precent").css("width",t.percent+"%")},FileUploaded:function(e,s,l){var o=JSON.parse(l.response);_.isUndefined(o.widgets)?alert(panelsOptions.plupload.error_message):(t.uploadedLayout=o,i.find(".progress-bar").hide(),t.$(".js-so-selected-file").text(panelsOptions.loc.ready_to_insert.replace("%s",s.name)),t.updateButtonState(!0))},Error:function(){alert(panelsOptions.plupload.error_message)}}}).init(),i.find(".drag-upload-area").on("dragover",function(){l(this).addClass("file-dragover")}).on("dragleave",function(){l(this).removeClass("file-dragover")}),e.find(".so-export").submit(function(e){var i=l(this),s=t.builder.model.getPanelsData(),o=l('input[name="post_title"]').val();o||(o=l('input[name="post_ID"]').val()),s.name=o,i.find('input[name="panels_export_data"]').val(JSON.stringify(s))})},displayLayoutDirectory:function(e,t,i){var s=this,o=this.$(".so-content").empty().addClass("so-panels-loading");if(void 0===e&&(e=""),void 0===t&&(t=1),void 0===i&&(i="directory-siteorigin"),i.match("^directory-")&&!panelsOptions.directory_enabled)return o.removeClass("so-panels-loading").html(l("#siteorigin-panels-directory-enable").html()),void o.find(".so-panels-enable-directory").click(function(n){n.preventDefault(),l.get(panelsOptions.ajaxurl,{action:"so_panels_directory_enable"},function(){}),panelsOptions.directory_enabled=!0,o.addClass("so-panels-loading"),s.displayLayoutDirectory(e,t,i)});l.get(panelsOptions.ajaxurl,{action:"so_panels_layouts_query",search:e,page:t,type:i},function(n){if(s.currentTab===i){o.removeClass("so-panels-loading").html(s.directoryTemplate(n));var a=o.find(".so-previous"),r=o.find(".so-next");t<=1?a.addClass("button-disabled"):a.click(function(i){i.preventDefault(),s.displayLayoutDirectory(e,t-1,s.currentTab)}),t===n.max_num_pages||0===n.max_num_pages?r.addClass("button-disabled"):r.click(function(i){i.preventDefault(),s.displayLayoutDirectory(e,t+1,s.currentTab)}),o.find(".so-screenshot").each(function(){var e=l(this),t=e.find(".so-screenshot-wrapper");if(t.css("height",t.width()/4*3+"px").addClass("so-loading"),""!==e.data("src"))var i=l("<img/>").attr("src",e.data("src")).load(function(){t.removeClass("so-loading").css("height","auto"),i.appendTo(t).hide().fadeIn("fast")});else l("<img/>").attr("src",panelsOptions.prebuiltDefaultScreenshot).appendTo(t).hide().fadeIn("fast")}),o.find(".so-directory-browse").html(n.title)}},"json")},directoryItemClickHandler:function(e){var t=this.$(e.target).closest(".so-directory-item");this.$(".so-directory-items").find(".selected").removeClass("selected"),t.addClass("selected"),this.selectedLayoutItem={lid:t.data("layout-id"),type:t.data("layout-type")},this.updateButtonState(!0)},toolbarButtonClick:function(e){if(!this.canAddLayout())return!1;var t=e.data("value");if(_.isUndefined(t))return!1;if(this.updateButtonState(!1),e.hasClass("so-needs-confirm")&&!e.hasClass("so-confirmed")){if(this.updateButtonState(!0),e.hasClass("so-confirming"))return;e.addClass("so-confirming");var i=e.html();return e.html('<span class="dashicons dashicons-yes"></span>'+e.data("confirm")),setTimeout(function(){e.removeClass("so-confirmed").html(i)},2500),setTimeout(function(){e.removeClass("so-confirming"),e.addClass("so-confirmed")},200),!1}this.addingLayout=!0,"import"===this.currentTab?this.addLayoutToBuilder(this.uploadedLayout,t):this.loadSelectedLayout().then(function(e){this.addLayoutToBuilder(e,t)}.bind(this))},canAddLayout:function(){return(this.selectedLayoutItem||this.uploadedLayout)&&!this.addingLayout},loadSelectedLayout:function(){this.setStatusMessage(panelsOptions.loc.prebuilt_loading,!0);var e=_.extend(this.selectedLayoutItem,{action:"so_panels_get_layout"}),t=new l.Deferred;return l.get(panelsOptions.ajaxurl,e,function(e){var i="";e.success?t.resolve(e.data):(i=e.data.message,t.reject(e.data)),this.setStatusMessage(i,!1,!e.success),this.updateButtonState(!0)}.bind(this)),t.promise()},searchHandler:function(e){13===e.keyCode&&this.displayLayoutDirectory(l(e.currentTarget).val(),1,this.currentTab)},updateButtonState:function(e){e=e&&(this.selectedLayoutItem||this.uploadedLayout);var t=this.$(".so-import-layout");t.prop("disabled",!e),e?t.removeClass("disabled"):t.addClass("disabled")},addLayoutToBuilder:function(e,t){this.builder.addHistoryEntry("prebuilt_loaded"),this.builder.model.loadPanelsData(e,t),this.addingLayout=!1,this.closeDialog()}})},{}],8:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({cellPreviewTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-row-cell-preview").html())),editableLabel:!0,events:{"click .so-close":"closeDialog","click .so-toolbar .so-save":"saveHandler","click .so-toolbar .so-insert":"insertHandler","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler","change .row-set-form > *":"setCellsFromForm","click .row-set-form button.set-row":"setCellsFromForm"},dialogIcon:"add-row",dialogClass:"so-panels-dialog-row-edit",styleType:"row",dialogType:"edit",row:{cells:null,style:{}},cellStylesCache:[],initializeDialog:function(){this.on("open_dialog",function(){_.isUndefined(this.model)||_.isEmpty(this.model.get("cells"))?this.setRowModel(null):this.setRowModel(this.model),this.regenerateRowPreview()},this),this.row={cells:new s.collection.cells([{weight:.5},{weight:.5}]),style:{}},this.dialogFormsLoaded=0;var e=this;this.on("form_loaded styles_loaded",function(){2===++this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("close_dialog",this.closeHandler),this.on("edit_label",function(e){if(e!==panelsOptions.loc.row.add&&e!==panelsOptions.loc.row.edit||(e=""),this.model.set("label",e),_.isEmpty(e)){var t="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.$(".so-title").text(t)}}.bind(this))},setRowDialogType:function(e){this.dialogType=e},render:function(){var e="create"===this.dialogType?panelsOptions.loc.row.add:panelsOptions.loc.row.edit;this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-row").html(),{title:e,dialogType:this.dialogType}));var t=this.$(".so-title");this.model.has("label")&&!_.isEmpty(this.model.get("label"))&&t.text(this.model.get("label")),this.$(".so-edit-title").val(t.text()),this.styles=new s.view.styles,this.styles.model=this.model,this.styles.render("row",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this}),this.builder.supports("addRow")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteRow")||this.$(".so-buttons .so-delete").remove();var i=this.$(".so-sidebar.so-right-sidebar");return this.styles.attach(i),this.styles.on("styles_loaded",function(e){e?i.removeClass("so-panels-loading"):(i.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),i.remove())},this),i.addClass("so-panels-loading"),_.isUndefined(this.model)||(this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction"))),this.$("input.so-row-field").keyup(function(){l(this).trigger("change")}),this},setRowModel:function(e){return this.model=e,_.isEmpty(this.model)?this:(this.row={cells:this.model.get("cells").clone(),style:{},ratio:this.model.get("ratio"),ratio_direction:this.model.get("ratio_direction")},this.$('input[name="cells"].so-row-field').val(this.model.get("cells").length),this.model.has("ratio")&&this.$('select[name="ratio"].so-row-field').val(this.model.get("ratio")),this.model.has("ratio_direction")&&this.$('select[name="ratio_direction"].so-row-field').val(this.model.get("ratio_direction")),this.clearCellStylesCache(),this)},regenerateRowPreview:function(){var e=this,t=this.$(".row-preview"),i=this.getSelectedCellIndex();t.empty();var s;this.row.cells.each(function(o,n){var a=l(this.cellPreviewTemplate({weight:o.get("weight")}));t.append(a),n==i&&a.find(".preview-cell-in").addClass("cell-selected");var r,d=a.prev();d.length&&(r=l('<div class="resize-handle"></div>'),r.appendTo(a).dblclick(function(){var t=e.row.cells.at(n-1),i=o.get("weight")+t.get("weight");o.set("weight",i/2),t.set("weight",i/2),e.scaleRowWidths()}),r.draggable({axis:"x",containment:t,start:function(e,t){var i=a.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:a.outerWidth(),left:6,height:a.outerHeight()});i.find(".resize-handle").remove();var s=d.clone().appendTo(t.helper).css({position:"absolute",top:"0",width:d.outerWidth(),right:6,height:d.outerHeight()});s.find(".resize-handle").remove(),l(this).data({newCellClone:i,prevCellClone:s}),a.find("> .preview-cell-in").css("visibility","hidden"),d.find("> .preview-cell-in").css("visibility","hidden")},drag:function(i,s){var o=e.row.cells.at(n).get("weight"),a=e.row.cells.at(n-1).get("weight"),r=o-(s.position.left+6)/t.width(),d=a+(s.position.left+6)/t.width();s.helper.offset().left,t.offset().left;l(this).data("newCellClone").css("width",t.width()*r).find(".preview-cell-weight").html(Math.round(1e3*r)/10),l(this).data("prevCellClone").css("width",t.width()*d).find(".preview-cell-weight").html(Math.round(1e3*d)/10)},stop:function(i,s){l(this).data("newCellClone").remove(),l(this).data("prevCellClone").remove(),a.find(".preview-cell-in").css("visibility","visible"),d.find(".preview-cell-in").css("visibility","visible");var o=s.position.left+6,r=o/t.width(),c=e.row.cells.at(n),h=e.row.cells.at(n-1);c.get("weight")-r>.02&&h.get("weight")+r>.02&&(c.set("weight",c.get("weight")-r),h.set("weight",h.get("weight")+r)),e.scaleRowWidths(),s.helper.css("left",-6)}})),a.click(function(e){if(l(e.target).is(".preview-cell")||l(e.target).is(".preview-cell-in")){var t=l(e.target);t.closest(".row-preview").find(".preview-cell .preview-cell-in").removeClass("cell-selected"),t.addClass("cell-selected"),this.openSelectedCellStyles()}}.bind(this)),a.find(".preview-cell-weight").click(function(i){e.$(".resize-handle").css("pointer-event","none").draggable("disable"),t.find(".preview-cell-weight").each(function(){var i=jQuery(this).hide();l('<input type="text" class="preview-cell-weight-input no-user-interacted" />').val(parseFloat(i.html())).insertAfter(i).focus(function(){clearTimeout(s)}).keyup(function(e){9!==e.keyCode&&l(this).removeClass("no-user-interacted"),13===e.keyCode&&(e.preventDefault(),l(this).blur())}).keydown(function(e){if(9===e.keyCode){e.preventDefault();var i=t.find(".preview-cell-weight-input"),s=i.index(l(this));s===i.length-1?i.eq(0).focus().select():i.eq(s+1).focus().select()}}).blur(function(){t.find(".preview-cell-weight-input").each(function(t,i){isNaN(parseFloat(l(i).val()))&&l(i).val(Math.floor(1e3*e.row.cells.at(t).get("weight"))/10)}),s=setTimeout(function(){if(0===t.find(".preview-cell-weight-input").length)return!1;var i=[],s=[],o=0,n=0;if(t.find(".preview-cell-weight-input").each(function(t,a){var r=parseFloat(l(a).val());r=isNaN(r)?1/e.row.cells.length:Math.round(10*r)/1e3;var d=!l(a).hasClass("no-user-interacted");i.push(r),s.push(d),d?o+=r:n+=r}),o>0&&n>0&&1-o>0)for(var a=0;a<i.length;a++)s[a]||(i[a]=i[a]/n*(1-o));var r=_.reduce(i,function(e,t){return e+t});i=i.map(function(e){return e/r}),Math.min.apply(Math,i)>.01&&e.row.cells.each(function(e,t){e.set("weight",i[t])}),t.find(".preview-cell").each(function(t,i){var s=e.row.cells.at(t).get("weight");l(i).animate({width:Math.round(1e3*s)/10+"%"},250),l(i).find(".preview-cell-weight-input").val(Math.round(1e3*s)/10)}),t.find(".preview-cell").css("overflow","visible"),setTimeout(function(){e.regenerateRowPreview()},260)},100)}).click(function(){l(this).select()})}),l(this).siblings(".preview-cell-weight-input").select()})},this),this.openSelectedCellStyles(),this.trigger("form_loaded",this)},getSelectedCellIndex:function(){var e=-1;return this.$(".preview-cell .preview-cell-in").each(function(t,i){l(i).is(".cell-selected")&&(e=t)}),e},openSelectedCellStyles:function(){if(!_.isUndefined(this.cellStyles)){if(this.cellStyles.stylesLoaded){var e={};try{e=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",e)}this.cellStyles.detach()}if(this.cellStyles=this.getSelectedCellStyles(),this.cellStyles){var t=this.$(".so-sidebar.so-right-sidebar");this.cellStyles.attach(t),this.cellStyles.stylesLoaded||(this.cellStyles.on("styles_loaded",function(){t.removeClass("so-panels-loading")},this),t.addClass("so-panels-loading"))}},getSelectedCellStyles:function(){var e=this.getSelectedCellIndex();if(e>-1){var t=this.cellStylesCache[e];t||(t=new s.view.styles,t.model=this.row.cells.at(e),t.render("cell",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this,index:e}),this.cellStylesCache[e]=t)}return t},clearCellStylesCache:function(){this.cellStylesCache.forEach(function(e){e.remove()}),this.cellStylesCache=[]},scaleRowWidths:function(){var e=this;this.$(".row-preview .preview-cell").each(function(t,i){var s=e.row.cells.at(t);l(i).css("width",100*s.get("weight")+"%").find(".preview-cell-weight").html(Math.round(1e3*s.get("weight"))/10)})},setCellsFromForm:function(){try{var e={cells:parseInt(this.$('.row-set-form input[name="cells"]').val()),ratio:parseFloat(this.$('.row-set-form select[name="ratio"]').val()),direction:this.$('.row-set-form select[name="ratio_direction"]').val()};_.isNaN(e.cells)&&(e.cells=1),isNaN(e.ratio)&&(e.ratio=1),e.cells<1?(e.cells=1,this.$('.row-set-form input[name="cells"]').val(e.cells)):e.cells>12&&(e.cells=12,this.$('.row-set-form input[name="cells"]').val(e.cells)),this.$('.row-set-form select[name="ratio"]').val(e.ratio);for(var t=[],i=this.row.cells.length!==e.cells,o=1,n=0;n<e.cells;n++)t.push(o),o*=e.ratio;var a=_.reduce(t,function(e,t){return e+t});if(t=_.map(t,function(e){return e/a}),t=_.filter(t,function(e){return e>.01}),"left"===e.direction&&(t=t.reverse()),this.row.cells=new s.collection.cells(this.row.cells.first(t.length)),_.each(t,function(e,t){var i=this.row.cells.at(t);i?i.set("weight",e):(i=new s.model.cell({weight:e,row:this.model}),this.row.cells.add(i))}.bind(this)),this.row.ratio=e.ratio,this.row.ratio_direction=e.direction,i)this.regenerateRowPreview();else{var r=this;this.$(".preview-cell").each(function(e,t){var i=r.row.cells.at(e).get("weight");l(t).animate({width:Math.round(1e3*i)/10+"%"},250),l(t).find(".preview-cell-weight").html(Math.round(1e3*i)/10)}),this.$(".preview-cell").css("overflow","visible"),setTimeout(function(){r.regenerateRowPreview()},260)}}catch(e){console.log("Error setting cells - "+e.message)}this.$(".row-set-form .so-button-row-set").removeClass("button-primary")},tabClickHandler:function(e){"#row-layout"===e.attr("href")?this.$(".so-panels-dialog").addClass("so-panels-dialog-has-right-sidebar"):this.$(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar")},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),_.isEmpty(this.model)||(this.model.setCells(this.row.cells),this.model.set("ratio",this.row.ratio),this.model.set("ratio_direction",this.row.ratio_direction)),!_.isUndefined(this.styles)&&this.styles.stylesLoaded){var t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-row-styles").style}catch(e){console.log("Error retrieving row styles - "+e.message)}this.model.set("style",t)}if(!_.isUndefined(this.cellStyles)&&this.cellStyles.stylesLoaded){var t={};try{t=this.getFormValues(".so-sidebar .so-visual-styles.so-cell-styles").style}catch(e){console.log("Error retrieving cell styles - "+e.message)}this.cellStyles.model.set("style",t)}e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},insertHandler:function(){this.builder.addHistoryEntry("row_added"),this.updateModel();var e=this.builder.getActiveCell({createCell:!1}),t={};return null!==e&&(t.at=this.builder.model.get("rows").indexOf(e.row)+1),this.model.collection=this.builder.model.get("rows"),this.builder.model.get("rows").add(this.model,t),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},saveHandler:function(){return this.builder.addHistoryEntry("row_edited"),this.updateModel(),this.closeDialog(),this.builder.model.refreshPanelsData(),!1},deleteHandler:function(){return this.model.trigger("visual_destroy"),this.closeDialog({silent:!0}),!1},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);return this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.closeDialog({silent:!0}),!1},closeHandler:function(){this.clearCellStylesCache(),_.isUndefined(this.cellStyles)||(this.cellStyles=void 0)}})},{}],9:[function(e,t,i){var s=window.panels,l=jQuery,o=e("../view/widgets/js-widget");t.exports=s.view.dialog.extend({builder:null,sidebarWidgetTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-widget-sidebar-widget").html())),dialogClass:"so-panels-dialog-edit-widget",dialogIcon:"add-widget",widgetView:!1,savingWidget:!1,editableLabel:!0,events:{"click .so-close":"saveHandler","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext","click .so-toolbar .so-delete":"deleteHandler","click .so-toolbar .so-duplicate":"duplicateHandler"},initializeDialog:function(){var e=this;this.model.on("change:values",this.handleChangeValues,this),this.model.on("destroy",this.remove,this),this.dialogFormsLoaded=0,this.on("form_loaded styles_loaded",function(){2===++this.dialogFormsLoaded&&e.updateModel({refreshArgs:{silent:!0}})}),this.on("edit_label",function(e){e===panelsOptions.widgets[this.model.get("class")].title&&(e=""),this.model.set("label",e),_.isEmpty(e)&&this.$(".so-title").text(this.model.getWidgetField("title"))}.bind(this))},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-widget").html(),{})),this.loadForm();var e=this.model.getWidgetField("title");this.$(".so-title .widget-name").html(e),this.$(".so-edit-title").val(e),this.builder.supports("addWidget")||this.$(".so-buttons .so-duplicate").remove(),this.builder.supports("deleteWidget")||this.$(".so-buttons .so-delete").remove(),this.styles=new s.view.styles,this.styles.model=this.model,this.styles.render("widget",this.builder.config.postId,{builderType:this.builder.config.builderType,dialog:this});var t=this.$(".so-sidebar.so-right-sidebar");this.styles.attach(t),this.styles.on("styles_loaded",function(e){e?t.removeClass("so-panels-loading"):(t.closest(".so-panels-dialog").removeClass("so-panels-dialog-has-right-sidebar"),t.remove())},this),t.addClass("so-panels-loading")},getPrevDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t=e.index(this.widgetView.$el);if(0===t)return!1;do{if(widgetView=e.eq(--t).data("view"),!_.isUndefined(widgetView)&&!widgetView.model.get("read_only"))return widgetView.getEditDialog()}while(!_.isUndefined(widgetView)&&t>0);return!1},getNextDialog:function(){var e=this.builder.$(".so-cells .cell .so-widget");if(e.length<=1)return!1;var t,i=e.index(this.widgetView.$el);if(i===e.length-1)return!1;do{if(t=e.eq(++i).data("view"),!_.isUndefined(t)&&!t.model.get("read_only"))return t.getEditDialog()}while(!_.isUndefined(t));return!1},loadForm:function(){if(this.$("> *").length){this.$(".so-content").addClass("so-panels-loading");var e={action:"so_panels_widget_form",widget:this.model.get("class"),instance:JSON.stringify(this.model.get("values")),raw:this.model.get("raw")};l.post(panelsOptions.ajaxurl,e,function(e){var t=e.replace(/{\$id}/g,this.model.cid),i=this.$(".so-content");i.removeClass("so-panels-loading").html(t),this.trigger("form_loaded",this),this.$(".panel-dialog").trigger("panelsopen"),this.on("close_dialog",this.updateModel,this),i.find("> .widget-content").length>0&&o.addWidget(i,this.model.widget_id)}.bind(this),"html")}},updateModel:function(e){if(e=_.extend({refresh:!0,refreshArgs:null},e),this.savingWidget=!0,!this.model.get("missing")){var t=this.getFormValues();_.isUndefined(t.widgets)?t={}:(t=t.widgets,t=t[Object.keys(t)[0]]),this.model.setValues(t),this.model.set("raw",!0)}if(this.styles.stylesLoaded){var i={};try{i=this.getFormValues(".so-sidebar .so-visual-styles").style}catch(e){}this.model.set("style",i)}this.savingWidget=!1,e.refresh&&this.builder.model.refreshPanelsData(e.refreshArgs)},handleChangeValues:function(){this.savingWidget||this.loadForm()},saveHandler:function(){this.builder.addHistoryEntry("widget_edited"),this.closeDialog()},deleteHandler:function(){return this.model.trigger("visual_destroy"),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1},duplicateHandler:function(){return this.model.trigger("user_duplicate"),this.closeDialog({silent:!0}),this.builder.model.refreshPanelsData(),!1}})},{"../view/widgets/js-widget":31}],10:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=s.view.dialog.extend({builder:null,widgetTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-widgets-widget").html())),filter:{},dialogClass:"so-panels-dialog-add-widget",dialogIcon:"add-widget",events:{"click .so-close":"closeDialog","click .widget-type":"widgetClickHandler","keyup .so-sidebar-search":"searchHandler"},initializeDialog:function(){this.on("open_dialog",function(){this.filter.search="",this.filterWidgets(this.filter)},this),this.on("open_dialog_complete",function(){this.$(".so-sidebar-search").val("").focus(),this.balanceWidgetHeights()}),this.on("tab_click",this.tabClickHandler,this)},render:function(){this.renderDialog(this.parseDialogContent(l("#siteorigin-panels-dialog-widgets").html(),{})),_.each(panelsOptions.widgets,function(e){var t=l(this.widgetTemplate({title:e.title,description:e.description}));_.isUndefined(e.icon)&&(e.icon="dashicons dashicons-admin-generic"),l('<span class="widget-icon" />').addClass(e.icon).prependTo(t.find(".widget-type-wrapper")),t.data("class",e.class).appendTo(this.$(".widget-type-list"))},this);var e=this.$(".so-sidebar-tabs");_.each(panelsOptions.widget_dialog_tabs,function(t){l(this.dialogTabTemplate({title:t.title})).data({message:t.message,filter:t.filter}).appendTo(e)},this),this.initTabs();var t=this;l(window).resize(function(){t.balanceWidgetHeights()})},tabClickHandler:function(e){this.filter=e.parent().data("filter"),this.filter.search=this.$(".so-sidebar-search").val();var t=e.parent().data("message");return _.isEmpty(t)&&(t=""),this.$(".so-toolbar .so-status").html(t),this.filterWidgets(this.filter),!1},searchHandler:function(e){if(13===e.which){var t=this.$(".widget-type-list .widget-type:visible");1===t.length&&t.click()}else this.filter.search=l(e.target).val().trim(),this.filterWidgets(this.filter)},filterWidgets:function(e){_.isUndefined(e)&&(e={}),_.isUndefined(e.groups)&&(e.groups=""),this.$(".widget-type-list .widget-type").each(function(){var t,i=l(this),s=i.data("class"),o=_.isUndefined(panelsOptions.widgets[s])?null:panelsOptions.widgets[s];t=!!_.isEmpty(e.groups)||null!==o&&!_.isEmpty(_.intersection(e.groups,panelsOptions.widgets[s].groups)),t&&(_.isUndefined(e.search)||""===e.search||-1===o.title.toLowerCase().indexOf(e.search.toLowerCase())&&(t=!1)),t?i.show():i.hide()}),this.balanceWidgetHeights()},
2
  widgetClickHandler:function(e){this.builder.addHistoryEntry("widget_added");var t=l(e.currentTarget),i=new s.model.widget({class:t.data("class")});i.cell=this.builder.getActiveCell(),i.cell.get("widgets").add(i),this.closeDialog(),this.builder.model.refreshPanelsData()},balanceWidgetHeights:function(e){var t=[[]],i=null,s=Math.round(this.$(".widget-type").parent().width()/this.$(".widget-type").width());this.$(".widget-type").css("clear","none").filter(":visible").each(function(e,t){e%s==0&&0!==e&&l(t).css("clear","both")}),this.$(".widget-type-wrapper").css("height","auto").filter(":visible").each(function(e,s){var o=l(s);null!==i&&i.position().top!==o.position().top&&(t[t.length]=[]),i=o,t[t.length-1].push(o)}),_.each(t,function(e,t){var i=_.max(e.map(function(e){return e.height()}));_.each(e,function(e){e.height(i)})})}})},{}],11:[function(e,t,i){t.exports={canCopyPaste:function(){return"undefined"!=typeof Storage&&panelsOptions.user},setModel:function(e){if(!this.canCopyPaste())return!1;var t=panels.helpers.serialize.serialize(e);return e instanceof panels.model.row?t.thingType="row-model":e instanceof panels.model.widget&&(t.thingType="widget-model"),localStorage["panels_clipboard_"+panelsOptions.user]=JSON.stringify(t),!0},isModel:function(e){if(!this.canCopyPaste())return!1;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&(t=JSON.parse(t),t.thingType&&t.thingType===e)},getModel:function(e){if(!this.canCopyPaste())return null;var t=localStorage["panels_clipboard_"+panelsOptions.user];return void 0!==t&&(t=JSON.parse(t),t.thingType&&t.thingType===e)?panels.helpers.serialize.unserialize(t,t.thingType,null):null}}},{}],12:[function(e,t,i){t.exports={lock:function(){if("hidden"!==jQuery("body").css("overflow")){var e=[self.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft,self.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop];jQuery("body").data({"scroll-position":e}).css("overflow","hidden"),_.isUndefined(e)||window.scrollTo(e[0],e[1])}},unlock:function(){if("hidden"===jQuery("body").css("overflow")&&!jQuery(".so-panels-dialog-wrapper").is(":visible")&&!jQuery(".so-panels-live-editor").is(":visible")){jQuery("body").css("overflow","visible");var e=jQuery("body").data("scroll-position");_.isUndefined(e)||window.scrollTo(e[0],e[1])}}}},{}],13:[function(e,t,i){t.exports={serialize:function(e){var t;if(e instanceof Backbone.Model){var i={};for(var s in e.attributes)if(e.attributes.hasOwnProperty(s)){if("builder"===s||"collection"===s)continue;t=e.attributes[s],t instanceof Backbone.Model||t instanceof Backbone.Collection?i[s]=this.serialize(t):i[s]=t}return i}if(e instanceof Backbone.Collection){for(var l=[],o=0;o<e.models.length;o++)t=e.models[o],t instanceof Backbone.Model||t instanceof Backbone.Collection?l.push(this.serialize(t)):l.push(t);return l}},unserialize:function(e,t,i){var s;switch(t){case"row-model":s=new panels.model.row,s.builder=i,s.set("style",e.style),s.setCells(this.unserialize(e.cells,"cell-collection",s));break;case"cell-model":s=new panels.model.cell,s.row=i,s.set("weight",e.weight),s.set("style",e.style),s.set("widgets",this.unserialize(e.widgets,"widget-collection",s));break;case"widget-model":s=new panels.model.widget,s.cell=i;for(var l in e)e.hasOwnProperty(l)&&s.set(l,e[l]);s.set("widget_id",panels.helpers.utils.generateUUID());break;case"cell-collection":s=new panels.collection.cells;for(var o=0;o<e.length;o++)s.push(this.unserialize(e[o],"cell-model",i));break;case"widget-collection":s=new panels.collection.widgets;for(var o=0;o<e.length;o++)s.push(this.unserialize(e[o],"widget-model",i));break;default:console.log("Unknown Thing - "+t)}return s}}},{}],14:[function(e,t,i){t.exports={generateUUID:function(){var e=(new Date).getTime();return window.performance&&"function"==typeof window.performance.now&&(e+=performance.now()),"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var i=(e+16*Math.random())%16|0;return e=Math.floor(e/16),("x"==t?i:3&i|8).toString(16)})},processTemplate:function(e){return _.isUndefined(e)||_.isNull(e)?"":(e=e.replace(/{{%/g,"<%"),e=e.replace(/%}}/g,"%>"),e=e.trim())},selectElementContents:function(e){var t=document.createRange();t.selectNodeContents(e);var i=window.getSelection();i.removeAllRanges(),i.addRange(t)}}},{}],15:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=function(e){return this.each(function(){var t=jQuery(this),i=t.closest("form").find(".widget-id").val(),o=l.extend(!0,{},e);if(_.isUndefined(i)||!(i.indexOf("__i__")>-1)){var n=new s.model.builder,a=new s.view.builder({model:n,config:o}),r=t.closest(".so-panels-dialog-wrapper").data("view");_.isUndefined(r)||(r.on("close_dialog",function(){n.refreshPanelsData()}),r.on("open_dialog_complete",function(){a.trigger("builder_resize")}),r.model.on("destroy",function(){n.emptyRows().destroy()}),a.setDialogParents(panelsOptions.loc.layout_widget,r));var d=Boolean(t.closest(".widget-content").length);a.render().attach({container:t,dialog:d||"dialog"===t.data("mode"),type:t.data("type")}).setDataField(t.find("input.panels-data")),d||"dialog"===t.data("mode")?(a.setDialogParents(panelsOptions.loc.layout_widget,a.dialog),t.find(".siteorigin-panels-display-builder").click(function(e){e.preventDefault(),a.dialog.openDialog()})):t.find(".siteorigin-panels-display-builder").parent().remove(),l(document).trigger("panels_setup",a)}})}},{}],16:[function(e,t,i){var s={};window.panels=s,window.siteoriginPanels=s,s.helpers={},s.helpers.clipboard=e("./helpers/clipboard"),s.helpers.utils=e("./helpers/utils"),s.helpers.serialize=e("./helpers/serialize"),s.helpers.pageScroll=e("./helpers/page-scroll"),s.model={},s.model.widget=e("./model/widget"),s.model.cell=e("./model/cell"),s.model.row=e("./model/row"),s.model.builder=e("./model/builder"),s.model.historyEntry=e("./model/history-entry"),s.collection={},s.collection.widgets=e("./collection/widgets"),s.collection.cells=e("./collection/cells"),s.collection.rows=e("./collection/rows"),s.collection.historyEntries=e("./collection/history-entries"),s.view={},s.view.widget=e("./view/widget"),s.view.cell=e("./view/cell"),s.view.row=e("./view/row"),s.view.builder=e("./view/builder"),s.view.dialog=e("./view/dialog"),s.view.styles=e("./view/styles"),s.view.liveEditor=e("./view/live-editor"),s.dialog={},s.dialog.builder=e("./dialog/builder"),s.dialog.widgets=e("./dialog/widgets"),s.dialog.widget=e("./dialog/widget"),s.dialog.prebuilt=e("./dialog/prebuilt"),s.dialog.row=e("./dialog/row"),s.dialog.history=e("./dialog/history"),s.utils={},s.utils.menu=e("./utils/menu"),jQuery.fn.soPanelsSetupBuilderWidget=e("./jquery/setup-builder-widget"),jQuery(function(e){var t,i,s,l,o=e("#siteorigin-panels-metabox");if(s=e("form#post"),o.length&&s.length)t=o,i=o.find(".siteorigin-panels-data-field"),l={editorType:"tinyMCE",postId:e("#post_ID").val(),editorId:"#content",builderType:o.data("builder-type"),builderSupports:o.data("builder-supports"),loadOnAttach:panelsOptions.loadOnAttach&&1==e("#auto_draft").val(),loadLiveEditor:1==o.data("live-editor"),liveEditorPreview:t.data("preview-url")};else if(e(".siteorigin-panels-builder-form").length){var n=e(".siteorigin-panels-builder-form");t=n.find(".siteorigin-panels-builder-container"),i=n.find('input[name="panels_data"]'),s=n,l={editorType:"standalone",postId:n.data("post-id"),editorId:"#post_content",builderType:n.data("type"),builderSupports:n.data("builder-supports"),loadLiveEditor:!1,liveEditorPreview:n.data("preview-url")}}if(!_.isUndefined(t)){var a=window.siteoriginPanels,r=new a.model.builder,d=new a.view.builder({model:r,config:l});d.render().attach({container:t}).setDataField(i).attachToEditor(),s.submit(function(){r.refreshPanelsData()}),t.removeClass("so-panels-loading"),e(document).trigger("panels_setup",d,window.panels)}e(document).on("widget-added",function(t,i){e(i).find(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()}),e("body").hasClass("wp-customizer")||e(function(){e(".siteorigin-page-builder-widget").soPanelsSetupBuilderWidget()})})},{"./collection/cells":1,"./collection/history-entries":2,"./collection/rows":3,"./collection/widgets":4,"./dialog/builder":5,"./dialog/history":6,"./dialog/prebuilt":7,"./dialog/row":8,"./dialog/widget":9,"./dialog/widgets":10,"./helpers/clipboard":11,"./helpers/page-scroll":12,"./helpers/serialize":13,"./helpers/utils":14,"./jquery/setup-builder-widget":15,"./model/builder":17,"./model/cell":18,"./model/history-entry":19,"./model/row":20,"./model/widget":21,"./utils/menu":22,"./view/builder":23,"./view/cell":24,"./view/dialog":25,"./view/live-editor":26,"./view/row":27,"./view/styles":28,"./view/widget":29}],17:[function(e,t,i){t.exports=Backbone.Model.extend({layoutPosition:{BEFORE:"before",AFTER:"after",REPLACE:"replace"},rows:{},defaults:{data:{widgets:[],grids:[],grid_cells:[]}},initialize:function(){this.set("rows",new panels.collection.rows)},addRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var s=new panels.collection.cells(t);e=_.extend({collection:this.get("rows"),cells:s},e);var l=new panels.model.row(e);return l.builder=this,this.get("rows").add(l,i),l},loadPanelsData:function(e,t){try{t===this.layoutPosition.BEFORE?e=this.concatPanelsData(e,this.getPanelsData()):t===this.layoutPosition.AFTER&&(e=this.concatPanelsData(this.getPanelsData(),e)),this.emptyRows(),this.set("data",JSON.parse(JSON.stringify(e)),{silent:!0});var i=[];if(_.isUndefined(e.grid_cells))return void this.trigger("load_panels_data");for(var s,l=0;l<e.grid_cells.length;l++)s=parseInt(e.grid_cells[l].grid),_.isUndefined(i[s])&&(i[s]=[]),i[s].push(e.grid_cells[l]);var o=this;if(_.each(i,function(t,i){var s={};_.isUndefined(e.grids[i].style)||(s.style=e.grids[i].style),_.isUndefined(e.grids[i].ratio)||(s.ratio=e.grids[i].ratio),_.isUndefined(e.grids[i].ratio_direction)||(s.ratio_direction=e.grids[i].ratio_direction),_.isUndefined(e.grids[i].color_label)||(s.color_label=e.grids[i].color_label),_.isUndefined(e.grids[i].label)||(s.label=e.grids[i].label),o.addRow(s,t,{noAnimate:!0})}),_.isUndefined(e.widgets))return;_.each(e.widgets,function(e){var t=null;_.isUndefined(e.panels_info)?(t=e.info,delete e.info):(t=e.panels_info,delete e.panels_info);var i=o.get("rows").at(parseInt(t.grid)),s=i.get("cells").at(parseInt(t.cell)),l=new panels.model.widget({class:t.class,values:e});_.isUndefined(t.style)||l.set("style",t.style),_.isUndefined(t.read_only)||l.set("read_only",t.read_only),_.isUndefined(t.widget_id)?l.set("widget_id",panels.helpers.utils.generateUUID()):l.set("widget_id",t.widget_id),_.isUndefined(t.label)||l.set("label",t.label),l.cell=s,s.get("widgets").add(l,{noAnimate:!0})}),this.trigger("load_panels_data")}catch(e){console.log("Error loading data: "+e.message)}},concatPanelsData:function(e,t){if(_.isUndefined(t)||_.isUndefined(t.grids)||_.isEmpty(t.grids)||_.isUndefined(t.grid_cells)||_.isEmpty(t.grid_cells))return e;if(_.isUndefined(e)||_.isUndefined(e.grids)||_.isEmpty(e.grids))return t;var i=e.grids.length,s=_.isUndefined(e.widgets)?0:e.widgets.length,l={grids:[],grid_cells:[],widgets:[]};l.grids=e.grids.concat(t.grids),_.isUndefined(e.grid_cells)||(l.grid_cells=e.grid_cells.slice()),_.isUndefined(e.widgets)||(l.widgets=e.widgets.slice());var o;for(o=0;o<t.grid_cells.length;o++){var n=t.grid_cells[o];n.grid=parseInt(n.grid)+i,l.grid_cells.push(n)}if(!_.isUndefined(t.widgets))for(o=0;o<t.widgets.length;o++){var a=t.widgets[o];a.panels_info.grid=parseInt(a.panels_info.grid)+i,a.panels_info.id=parseInt(a.panels_info.id)+s,l.widgets.push(a)}return l},getPanelsData:function(){var e={widgets:[],grids:[],grid_cells:[]},t=0;return this.get("rows").each(function(i,s){i.get("cells").each(function(i,l){i.get("widgets").each(function(i,o){var n={class:i.get("class"),raw:i.get("raw"),grid:s,cell:l,id:t++,widget_id:i.get("widget_id"),style:i.get("style"),label:i.get("label")};_.isEmpty(n.widget_id)&&(n.widget_id=panels.helpers.utils.generateUUID());var a=_.extend(_.clone(i.get("values")),{panels_info:n});e.widgets.push(a)}),e.grid_cells.push({grid:s,index:l,weight:i.get("weight"),style:i.get("style")})}),e.grids.push({cells:i.get("cells").length,style:i.get("style"),ratio:i.get("ratio"),ratio_direction:i.get("ratio_direction"),color_label:i.get("color_label"),label:i.get("label")})}),e},refreshPanelsData:function(e){e=_.extend({silent:!1},e);var t=this.get("data"),i=this.getPanelsData();this.set("data",i,{silent:!0}),e.silent||JSON.stringify(i)===JSON.stringify(t)||(this.trigger("change"),this.trigger("change:data"),this.trigger("refresh_panels_data",i,e))},emptyRows:function(){return _.invoke(this.get("rows").toArray(),"destroy"),this.get("rows").reset(),this},isValidLayoutPosition:function(e){return e===this.layoutPosition.BEFORE||e===this.layoutPosition.AFTER||e===this.layoutPosition.REPLACE},getPanelsDataFromHtml:function(e,t){var i=this,s=jQuery('<div id="wrapper">'+e+"</div>");if(s.find(".panel-layout .panel-grid").length){var l={grids:[],grid_cells:[],widgets:[]},o=new RegExp(panelsOptions.siteoriginWidgetRegex,"i"),n=function(){function e(e){return e&&"string"==typeof e&&(e=e.replace(/<script[^>]*>([\S\s]*?)<\/script>/gim,""),e=e.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gim,""),t.innerHTML=e,e=t.textContent,t.textContent=""),e}var t=document.createElement("div");return e}(),a=function(e){var t=e.find("div");if(!t.length)return e.html();var i;for(i=0;i<t.length-1&&jQuery.trim(t.eq(i).text())==jQuery.trim(t.eq(i+1).text());i++);var s=t.eq(i).find(".widget-title:header"),l="";return s.length&&(l=s.html(),s.remove()),{title:l,text:t.eq(i).html()}},r=s.find(".panel-layout").eq(0),d=function(e,t){return jQuery(t).closest(".panel-layout").is(r)};return s.find("> .panel-layout > .panel-grid").filter(d).each(function(e,s){var r=jQuery(s),c=r.find(".panel-grid-cell").filter(d);l.grids.push({cells:c.length,style:r.data("style"),ratio:r.data("ratio"),ratio_direction:r.data("ratio-direction"),color_label:r.data("color-label"),label:r.data("label")}),c.each(function(s,r){var c=jQuery(r),h=c.find(".so-panel").filter(d);l.grid_cells.push({grid:e,weight:_.isUndefined(c.data("weight"))?1:parseFloat(c.data("weight")),style:c.data("style")}),h.each(function(r,d){var c=jQuery(d),h=c.find(".panel-widget-style").length?c.find(".panel-widget-style").html():c.html(),u={grid:e,cell:s,style:c.data("style"),raw:!1,label:c.data("label")};h=h.trim();var p=o.exec(h);if(!_.isNull(p)&&""===h.replace(o,"").trim()){try{var g=/class="(.*?)"/.exec(p[3]),f=jQuery(p[5]),w=JSON.parse(n(f.val())),m=w.instance;u.class=g[1].replace(/\\\\+/g,"\\"),u.raw=!1,m.panels_info=u,l.widgets.push(m)}catch(e){u.class=t,l.widgets.push(_.extend(a(c),{filter:"1",type:"visual",panels_info:u}))}return!0}if(-1!==h.indexOf("panel-layout")){if(jQuery("<div>"+h+"</div>").find(".panel-layout .panel-grid").length)return u.class="SiteOrigin_Panels_Widgets_Layout",l.widgets.push({panels_data:i.getPanelsDataFromHtml(h,t),panels_info:u}),!0}return u.class=t,l.widgets.push(_.extend(a(c),{filter:"1",type:"visual",panels_info:u})),!0})})}),s.find(".panel-layout").remove(),s.find("style[data-panels-style-for-post]").remove(),s.html().replace(/^\s+|\s+$/gm,"").length&&(l.grids.push({cells:1,style:{}}),l.grid_cells.push({grid:l.grids.length-1,weight:1}),l.widgets.push({filter:"1",text:s.html().replace(/^\s+|\s+$/gm,""),title:"",type:"visual",panels_info:{class:t,raw:!1,grid:l.grids.length-1,cell:0}})),l}return{grid_cells:[{grid:0,weight:1}],grids:[{cells:1}],widgets:[{filter:"1",text:e,title:"",type:"visual",panels_info:{class:t,raw:!1,grid:0,cell:0}}]}}})},{}],18:[function(e,t,i){t.exports=Backbone.Model.extend({widgets:{},row:null,defaults:{weight:0,style:{}},indexes:null,initialize:function(){this.set("widgets",new panels.collection.widgets),this.on("destroy",this.onDestroy,this)},onDestroy:function(){_.invoke(this.get("widgets").toArray(),"destroy"),this.get("widgets").reset()},clone:function(e,t){_.isUndefined(e)&&(e=this.row),t=_.extend({cloneWidgets:!0},t);var i=new this.constructor(this.attributes);return i.set("collection",e.get("cells"),{silent:!0}),i.row=e,t.cloneWidgets&&this.get("widgets").each(function(e){i.get("widgets").add(e.clone(i,t),{silent:!0})}),i}})},{}],19:[function(e,t,i){t.exports=Backbone.Model.extend({defaults:{text:"",data:"",time:null,count:1}})},{}],20:[function(e,t,i){t.exports=Backbone.Model.extend({builder:null,defaults:{style:{}},indexes:null,initialize:function(){_.isEmpty(this.get("cells"))?this.set("cells",new panels.collection.cells):this.get("cells").each(function(e){e.row=this}.bind(this)),this.on("destroy",this.onDestroy,this)},setCells:function(e){var t=this.get("cells")||new panels.collection.cells,i=[];t.each(function(s,l){var o=e.at(l);if(o)s.set("weight",o.get("weight"));else{for(var n=t.at(e.length-1),a=s.get("widgets").models.slice(),r=0;r<a.length;r++)a[r].moveToCell(n,{silent:!1});i.push(s)}}),_.each(i,function(e){t.remove(e)}),e.length>t.length&&_.each(e.slice(t.length,e.length),function(e){e.set({collection:t}),e.row=this,t.add(e)}.bind(this)),this.reweightCells()},reweightCells:function(){var e=0,t=this.get("cells");t.each(function(t){e+=t.get("weight")}),t.each(function(t){t.set("weight",t.get("weight")/e)}),this.trigger("reweight_cells")},onDestroy:function(){_.invoke(this.get("cells").toArray(),"destroy"),this.get("cells").reset()},clone:function(e){_.isUndefined(e)&&(e=this.builder);var t=new this.constructor(this.attributes);t.set("collection",e.get("rows"),{silent:!0}),t.builder=e;var i=new panels.collection.cells;return this.get("cells").each(function(e){i.add(e.clone(t),{silent:!0})}),t.set("cells",i),t}})},{}],21:[function(e,t,i){t.exports=Backbone.Model.extend({cell:null,defaults:{class:null,missing:!1,values:{},raw:!1,style:{},read_only:!1,widget_id:""},indexes:null,initialize:function(){var e=this.get("class");!_.isUndefined(panelsOptions.widgets[e])&&panelsOptions.widgets[e].installed||this.set("missing",!0)},getWidgetField:function(e){return _.isUndefined(panelsOptions.widgets[this.get("class")])?"title"===e||"description"===e?panelsOptions.loc.missing_widget[e]:"":this.has("label")&&!_.isEmpty(this.get("label"))?this.get("label"):panelsOptions.widgets[this.get("class")][e]},moveToCell:function(e,t,i){return t=_.extend({silent:!0},t),this.cell=e,this.collection.remove(this,t),e.get("widgets").add(this,_.extend({at:i},t)),this.trigger("move_to_cell",e,i),this},triggerEdit:function(){this.trigger("user_edit",this)},triggerDuplicate:function(){this.trigger("user_duplicate",this)},setValues:function(e){var t=!1;JSON.stringify(e)!==JSON.stringify(this.get("values"))&&(t=!0),this.set("values",e,{silent:!0}),t&&(this.trigger("change",this),this.trigger("change:values"))},clone:function(e,t){_.isUndefined(e)&&(e=this.cell);var i=new this.constructor(this.attributes),s=JSON.parse(JSON.stringify(this.get("values"))),l=function(e){return _.each(e,function(t,i){_.isString(i)&&"_"===i[0]?delete e[i]:_.isObject(e[i])&&l(e[i])}),e};return s=l(s),"SiteOrigin_Panels_Widgets_Layout"===this.get("class")&&(s.builder_id=Math.random().toString(36).substr(2)),i.set("widget_id",""),i.set("values",s,{silent:!0}),i.set("collection",e.get("widgets"),{silent:!0}),i.cell=e,i.isDuplicate=!0,i},getTitle:function(){var e=panelsOptions.widgets[this.get("class")];if(_.isUndefined(e))return this.get("class").replace(/_/g," ");if(!_.isUndefined(e.panels_title)&&!1===e.panels_title)return panelsOptions.widgets[this.get("class")].description;var t=this.get("values"),i=["title","text"];for(var s in t)t.hasOwnProperty(s)&&i.push(s);i=_.uniq(i);for(var l in i)if(!_.isUndefined(t[i[l]])&&_.isString(t[i[l]])&&""!==t[i[l]]&&"on"!==t[i[l]]&&"_"!==i[l][0]&&!jQuery.isNumeric(t[i[l]])){var o=t[i[l]];o=o.replace(/<\/?[^>]+(>|$)/g,"");var n=o.split(" ");return n=n.slice(0,20),n.join(" ")}return this.getWidgetField("description")}})},{}],22:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({wrapperTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-context-menu").html())),sectionTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-context-menu-section").html())),contexts:[],active:!1,events:{"keyup .so-search-wrapper input":"searchKeyUp"},initialize:function(){this.listenContextMenu(),this.render(),this.attach()},listenContextMenu:function(){var e=this;l(window).on("contextmenu",function(t){return e.active&&!e.isOverEl(e.$el,t)?(e.closeMenu(),e.active=!1,t.preventDefault(),!1):!!e.active||(e.active=!1,e.trigger("activate_context",t,e),void(e.active&&(t.preventDefault(),e.openMenu({left:t.pageX,top:t.pageY}))))})},render:function(){this.setElement(this.wrapperTemplate())},attach:function(){this.$el.appendTo("body")},openMenu:function(e){this.trigger("open_menu"),l(window).on("keyup",{menu:this},this.keyboardListen),l(window).on("click",{menu:this},this.clickOutsideListen),this.$el.css("max-height",l(window).height()-20),e.left+this.$el.outerWidth()+10>=l(window).width()&&(e.left=l(window).width()-this.$el.outerWidth()-10),e.left<=0&&(e.left=10),e.top+this.$el.outerHeight()-l(window).scrollTop()+10>=l(window).height()&&(e.top=l(window).height()+l(window).scrollTop()-this.$el.outerHeight()-10),e.left<=0&&(e.left=10),this.$el.css({left:e.left+1,top:e.top+1}).show(),this.$(".so-search-wrapper input").focus()},closeMenu:function(){this.trigger("close_menu"),l(window).off("keyup",this.keyboardListen),l(window).off("click",this.clickOutsideListen),this.active=!1,this.$el.empty().hide()},keyboardListen:function(e){var t=e.data.menu;switch(e.which){case 27:t.closeMenu()}},clickOutsideListen:function(e){var t=e.data.menu;3!==e.which&&t.$el.is(":visible")&&!t.isOverEl(t.$el,e)&&t.closeMenu()},addSection:function(e,t,i,s){var o=this;t=_.extend({display:5,defaultDisplay:!1,search:!0,sectionTitle:"",searchPlaceholder:"",titleKey:"title"},t);var n=l(this.sectionTemplate({settings:t,items:i})).attr("id","panels-menu-section-"+e);this.$el.append(n),n.find(".so-item:not(.so-confirm)").click(function(){var e=l(this);s(e.data("key")),o.closeMenu()}),n.find(".so-item.so-confirm").click(function(){var e=l(this);if(e.hasClass("so-confirming"))return s(e.data("key")),void o.closeMenu();e.data("original-text",e.html()).addClass("so-confirming").html('<span class="dashicons dashicons-yes"></span> '+panelsOptions.loc.dropdown_confirm),setTimeout(function(){e.removeClass("so-confirming"),e.html(e.data("original-text"))},2500)}),n.data("settings",t).find(".so-search-wrapper input").trigger("keyup"),this.active=!0},hasSection:function(e){return this.$el.find("#panels-menu-section-"+e).length>0},searchKeyUp:function(e){var t=l(e.currentTarget),i=t.closest(".so-section"),s=i.data("settings");if(38===e.which||40===e.which){var o=i.find("ul li:visible"),n=o.filter(".so-active").eq(0);if(n.length){o.removeClass("so-active");var a=o.index(n);38===e.which?n=a-1<0?o.last():o.eq(a-1):40===e.which&&(n=a+1>=o.length?o.first():o.eq(a+1))}else 38===e.which?n=o.last():40===e.which&&(n=o.first());return n.addClass("so-active"),!1}if(13===e.which)return 1===i.find("ul li:visible").length?(i.find("ul li:visible").trigger("click"),!1):(i.find("ul li.so-active:visible").trigger("click"),!1);if(""===t.val())if(s.defaultDisplay){i.find(".so-item").hide();for(var r=0;r<s.defaultDisplay.length;r++)i.find('.so-item[data-key="'+s.defaultDisplay[r]+'"]').show()}else i.find(".so-item").show();else i.find(".so-item").hide().each(function(){var e=l(this);-1!==e.html().toLowerCase().indexOf(t.val().toLowerCase())&&e.show()});i.find(".so-item:visible:gt("+(s.display-1)+")").hide(),0===i.find(".so-item:visible").length&&""!==t.val()?i.find(".so-no-results").show():i.find(".so-no-results").hide()},isOverEl:function(e,t){var i=[[e.offset().left,e.offset().top],[e.offset().left+e.outerWidth(),e.offset().top+e.outerHeight()]];return t.pageX>=i[0][0]&&t.pageX<=i[1][0]&&t.pageY>=i[0][1]&&t.pageY<=i[1][1]}})},{}],23:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({config:{},template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder").html())),dialogs:{},rowsSortable:null,dataField:!1,currentData:"",attachedToEditor:!1,attachedVisible:!1,liveEditor:void 0,menu:!1,activeCell:null,events:{"click .so-tool-button.so-widget-add":"displayAddWidgetDialog","click .so-tool-button.so-row-add":"displayAddRowDialog","click .so-tool-button.so-prebuilt-add":"displayAddPrebuiltDialog","click .so-tool-button.so-history":"displayHistoryDialog","click .so-tool-button.so-live-editor":"displayLiveEditor"},rows:null,initialize:function(e){var t=this;return this.config=_.extend({loadLiveEditor:!1,builderSupports:{}},e.config),this.config.builderSupports=_.extend({addRow:!0,editRow:!0,deleteRow:!0,moveRow:!0,addWidget:!0,editWidget:!0,deleteWidget:!0,moveWidget:!0,prebuilt:!0,history:!0,liveEditor:!0,revertToEditor:!0},this.config.builderSupports),e.config.loadLiveEditor&&this.on("builder_live_editor_added",function(){this.displayLiveEditor()}),this.dialogs={widgets:new s.dialog.widgets,row:new s.dialog.row,prebuilt:new s.dialog.prebuilt},_.each(this.dialogs,function(e,i,s){s[i].setBuilder(t)}),this.dialogs.row.setRowDialogType("create"),this.model.get("rows").on("add",this.onAddRow,this),l(window).resize(function(e){e.target===window&&t.trigger("builder_resize")}),this.model.on("change:data load_panels_data",this.storeModelData,this),this.on("content_change",this.handleContentChange,this),this.on("display_builder",this.handleDisplayBuilder,this),this.on("hide_builder",this.handleHideBuilder,this),this.on("builder_rendered builder_resize",this.handleBuilderSizing,this),this.model.on("change:data load_panels_data",this.toggleWelcomeDisplay,this),this.on("display_builder",this.wrapEditorExpandAdjust,this),this.menu=new s.utils.menu({}),this.menu.on("activate_context",this.activateContextMenu,this),this.config.loadOnAttach&&this.on("builder_attached_to_editor",function(){this.displayAttachedBuilder({confirm:!1})},this),this},render:function(){return this.setElement(this.template()),this.$el.attr("id","siteorigin-panels-builder-"+this.cid).addClass("so-builder-container"),this.trigger("builder_rendered"),this},attach:function(e){e=_.extend({container:!1,dialog:!1},e),e.dialog?(this.dialog=new s.dialog.builder,this.dialog.builder=this):(this.$el.appendTo(e.container),this.metabox=e.container.closest(".postbox"),this.initSortable(),this.trigger("attached_to_container",e.container)),this.trigger("builder_attached"),this.supports("liveEditor")&&this.addLiveEditor(),this.supports("history")&&this.addHistoryBrowser();var t=this.$(".so-builder-toolbar"),i=this.$(".so-panels-welcome-message"),l=panelsOptions.loc.welcomeMessage,o=[];this.supports("addWidget")?o.push(l.addWidgetButton):t.find(".so-widget-add").hide(),this.supports("addRow")?o.push(l.addRowButton):t.find(".so-row-add").hide(),this.supports("prebuilt")?o.push(l.addPrebuiltButton):t.find(".so-prebuilt-add").hide();var n="";3===o.length?n=l.threeEnabled:2===o.length?n=l.twoEnabled:1===o.length?n=l.oneEnabled:0===o.length&&(n=l.addingDisabled);var a=_.template(s.helpers.utils.processTemplate(n)),r=a({items:o})+" "+l.docsMessage;return i.find(".so-message-wrapper").html(r),this},attachToEditor:function(){if("tinyMCE"!==this.config.editorType)return this;this.attachedToEditor=!0;var e=this.metabox,t=this;l("#wp-content-wrap .wp-editor-tabs").find(".wp-switch-editor").click(function(e){e.preventDefault(),l("#wp-content-editor-container").show(),l("#wp-content-wrap").removeClass("panels-active"),l("#content-resize-handle").show(),t.trigger("hide_builder")}).end().append(l('<a id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">'+e.find(".hndle span").html()+"</a>").click(function(e){t.displayAttachedBuilder({confirm:!0})&&e.preventDefault()})),this.supports("revertToEditor")&&e.find(".so-switch-to-standard").click(function(i){i.preventDefault(),confirm(panelsOptions.loc.confirm_stop_builder)&&(t.addHistoryEntry("back_to_editor"),t.model.loadPanelsData(!1),l("#wp-content-wrap").show(),e.hide(),l(window).resize(),t.attachedVisible=!1,t.trigger("hide_builder"))}).show(),e.insertAfter("#wp-content-wrap").hide().addClass("attached-to-editor");var i=this.model.get("data");_.isEmpty(i.widgets)&&_.isEmpty(i.grids)&&this.supports("revertToEditor")||this.displayAttachedBuilder({confirm:!1});var s=function(){var e=t.$(".so-builder-toolbar");if(t.$el.hasClass("so-display-narrow"))return e.css({top:0,left:0,width:"100%",position:"absolute"}),void t.$el.css("padding-top",e.outerHeight());var i=l(window).scrollTop()-t.$el.offset().top;"fixed"===l("#wpadminbar").css("position")&&(i+=l("#wpadminbar").outerHeight());var s={top:0,bottom:t.$el.outerHeight()-e.outerHeight()+20};i>s.top&&i<s.bottom?"fixed"!==e.css("position")&&e.css({top:l("#wpadminbar").outerHeight(),left:t.$el.offset().left,width:t.$el.outerWidth(),position:"fixed"}):e.css({top:Math.min(Math.max(i,0),t.$el.outerHeight()-e.outerHeight()+20),left:0,width:"100%",position:"absolute"}),t.$el.css("padding-top",e.outerHeight())};return this.on("builder_resize",s,this),l(document).scroll(s),s(),this.trigger("builder_attached_to_editor"),this},displayAttachedBuilder:function(e){if(e=_.extend({confirm:!0},e),e.confirm){var t="undefined"!=typeof tinyMCE&&tinyMCE.get("content");if(""!==(t&&_.isFunction(t.getContent)?t.getContent():l("textarea#content").val())&&!confirm(panelsOptions.loc.confirm_use_builder))return!1}return l("#wp-content-wrap").hide(),l("#editor-expand-toggle").on("change.editor-expand",function(){l(this).prop("checked")||l("#wp-content-wrap").hide()}),this.metabox.show().find("> .inside").show(),l(window).resize(),l(document).scroll(),this.attachedVisible=!0,this.trigger("display_builder"),!0},initSortable:function(){if(!this.supports("moveRow"))return this;var e=this;return this.rowsSortable=this.$(".so-rows-container").sortable({appendTo:"#wpwrap",items:".so-row-container",handle:".so-row-move",axis:"y",tolerance:"pointer",scroll:!1,stop:function(t,i){e.addHistoryEntry("row_moved");var s=l(i.item),o=s.data("view");e.model.get("rows").remove(o.model,{silent:!0}),e.model.get("rows").add(o.model,{silent:!0,at:s.index()}),o.trigger("move",s.index()),e.model.refreshPanelsData()}}),this},refreshSortable:function(){_.isNull(this.rowsSortable)||this.rowsSortable.sortable("refresh")},setDataField:function(e,t){if(t=_.extend({load:!0},t),this.dataField=e,this.dataField.data("builder",this),t.load&&""!==e.val()){var i=this.dataField.val();try{i=JSON.parse(i)}catch(e){i={}}this.model.loadPanelsData(i),this.currentData=i,this.toggleWelcomeDisplay()}return this},storeModelData:function(){var e=JSON.stringify(this.model.get("data"));l(this.dataField).val()!==e&&(l(this.dataField).val(e),l(this.dataField).trigger("change"),this.trigger("content_change"))},onAddRow:function(e,t,i){i=_.extend({noAnimate:!1},i);var l=new s.view.row({model:e});l.builder=this,l.render(),_.isUndefined(i.at)||t.length<=1?l.$el.appendTo(this.$(".so-rows-container")):l.$el.insertAfter(this.$(".so-rows-container .so-row-container").eq(i.at-1)),!1===i.noAnimate&&l.visualCreate(),this.refreshSortable(),l.resize()},displayAddWidgetDialog:function(){this.dialogs.widgets.openDialog()},displayAddRowDialog:function(){var e=new s.model.row,t=new s.collection.cells([{weight:.5},{weight:.5}]);t.each(function(t){t.row=e}),e.set("cells",t),e.builder=this.model,this.dialogs.row.setRowModel(e),this.dialogs.row.openDialog()},displayAddPrebuiltDialog:function(){this.dialogs.prebuilt.openDialog()},displayHistoryDialog:function(){this.dialogs.history.openDialog()},pasteRowHandler:function(){var e=s.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof s.model.row&&(this.addHistoryEntry("row_pasted"),e.builder=this.model,this.model.get("rows").add(e,{at:this.model.get("rows").indexOf(this.model)+1}),this.model.refreshPanelsData())},getActiveCell:function(e){if(e=_.extend({createCell:!0},e),
3
+ !this.model.get("rows").length){if(!e.createCell)return null;this.model.addRow({},[{weight:1}],{noAnimate:!0})}var t=this.activeCell;return _.isEmpty(t)||-1===this.model.get("rows").indexOf(t.model.row)?this.model.get("rows").last().get("cells").first():t.model},addLiveEditor:function(){return _.isEmpty(this.config.liveEditorPreview)?this:(this.liveEditor=new s.view.liveEditor({builder:this,previewUrl:this.config.liveEditorPreview}),this.liveEditor.hasPreviewUrl()&&this.$(".so-builder-toolbar .so-live-editor").show(),this.trigger("builder_live_editor_added"),this)},displayLiveEditor:function(){_.isUndefined(this.liveEditor)||this.liveEditor.open()},addHistoryBrowser:function(){if(_.isEmpty(this.config.liveEditorPreview))return this;this.dialogs.history=new s.dialog.history,this.dialogs.history.builder=this,this.dialogs.history.entries.builder=this.model,this.dialogs.history.setRevertEntry(this.model),this.$(".so-builder-toolbar .so-history").show()},addHistoryEntry:function(e,t){_.isUndefined(t)&&(t=null),_.isUndefined(this.dialogs.history)||this.dialogs.history.entries.addEntry(e,t)},supports:function(e){return"rowAction"===e?this.supports("addRow")||this.supports("editRow")||this.supports("deleteRow"):"widgetAction"===e?this.supports("addWidget")||this.supports("editWidget")||this.supports("deleteWidget"):!_.isUndefined(this.config.builderSupports[e])&&this.config.builderSupports[e]},handleContentChange:function(){if(panelsOptions.copy_content&&this.attachedToEditor&&this.$el.is(":visible")){var e=this.model.getPanelsData();_.isEmpty(e.widgets)||l.post(panelsOptions.ajaxurl,{action:"so_panels_builder_content",panels_data:JSON.stringify(e),post_id:this.config.postId},function(e){""!==e&&this.updateEditorContent(e)}.bind(this))}},updateEditorContent:function(e){if("tinyMCE"!==this.config.editorType||"undefined"==typeof tinyMCE||_.isNull(tinyMCE.get("content"))){l(this.config.editorId).val(e).trigger("change").trigger("keyup")}else{var t=tinyMCE.get("content");t.setContent(e),t.fire("change"),t.fire("keyup")}this.triggerYoastSeoChange()},triggerYoastSeoChange:function(){if(l("#yoast_wpseo_focuskw_text_input").length){var e,t=document.getElementById("yoast_wpseo_focuskw_text_input");document.createEvent?(e=document.createEvent("HTMLEvents"),e.initEvent("keyup",!0,!0)):(e=document.createEventObject(),e.eventType="keyup"),e.eventName="keyup",document.createEvent?t.dispatchEvent(e):t.fireEvent("on"+e.eventType,e)}},handleDisplayBuilder:function(){var e="undefined"!=typeof tinyMCE&&tinyMCE.get("content"),t=e&&_.isFunction(e.getContent)?e.getContent():l("textarea#content").val();if((_.isEmpty(this.model.get("data"))||_.isEmpty(this.model.get("data").widgets)&&_.isEmpty(this.model.get("data").grids))&&""!==t){var i=panelsOptions.text_widget;if(_.isEmpty(i))return;this.model.loadPanelsData(this.model.getPanelsDataFromHtml(t,i)),this.model.trigger("change"),this.model.trigger("change:data")}l("#post-status-info").addClass("for-siteorigin-panels")},handleHideBuilder:function(){l("#post-status-info").show().removeClass("for-siteorigin-panels")},wrapEditorExpandAdjust:function(){try{for(var e,t=(l.hasData(window)&&l._data(window)).events.scroll,i=0;i<t.length;i++)if("editor-expand"===t[i].namespace){e=t[i],l(window).unbind("scroll",e.handler),l(window).bind("scroll",function(t){this.attachedVisible||e.handler(t)}.bind(this));break}}catch(e){return}},handleBuilderSizing:function(){var e=this.$el.width();return e?(e<480?this.$el.addClass("so-display-narrow"):this.$el.removeClass("so-display-narrow"),this):this},setDialogParents:function(e,t){_.each(this.dialogs,function(i,s,l){l[s].setParent(e,t)}),this.on("add_dialog",function(i){i.setParent(e,t)},this)},toggleWelcomeDisplay:function(){this.model.get("rows").isEmpty()?this.$(".so-panels-welcome-message").show():this.$(".so-panels-welcome-message").hide()},activateContextMenu:function(e,t){var i=this,s=l(".siteorigin-panels-builder:visible").sort(function(e,t){return l(e).zIndex()>l(t).zIndex()?1:-1}).last(),o=l(".so-panels-dialog-wrapper:visible").sort(function(e,t){return l(e).zIndex()>l(t).zIndex()?1:-1}).last(),n=i.$el.closest(".so-panels-dialog-wrapper");if(i.$el.is(s)&&(0===o.length||o.is(n))){var a=l([]).add(i.$(".so-panels-welcome-message:visible")).add(i.$(".so-rows-container > .so-row-container")).add(i.$(".so-cells > .cell")).add(i.$(".cell-wrapper > .so-widget")).filter(function(i){return t.isOverEl(l(this),e)}),r=a.last().data("view");void 0!==r&&void 0!==r.buildContextualMenu?r.buildContextualMenu(e,t):a.last().hasClass("so-panels-welcome-message")&&this.buildContextualMenu(e,t)}},buildContextualMenu:function(e,t){var i={};this.supports("addRow")&&(i.add_row={title:panelsOptions.loc.contextual.add_row}),s.helpers.clipboard.canCopyPaste()&&s.helpers.clipboard.isModel("row-model")&&this.supports("addRow")&&(i.paste_row={title:panelsOptions.loc.contextual.row_paste}),_.isEmpty(i)||t.addSection("builder-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},i,function(e){switch(e){case"add_row":this.displayAddRowDialog();break;case"paste_row":this.pasteRowHandler()}}.bind(this))}})},{}],24:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-cell").html())),events:{"click .cell-wrapper":"handleCellClick"},row:null,widgetSortable:null,initialize:function(){this.model.get("widgets").on("add",this.onAddWidget,this)},render:function(){var e={weight:this.model.get("weight"),totalWeight:this.row.model.get("cells").totalWeight()};this.setElement(this.template(e)),this.$el.data("view",this);var t=this;return this.model.get("widgets").each(function(e){var i=new s.view.widget({model:e});i.cell=t,i.render(),i.$el.appendTo(t.$(".widgets-container"))}),this.initSortable(),this.initResizable(),this},initSortable:function(){if(!this.row.builder.supports("moveWidget"))return this;var e=this,t=e.row.builder.$el.attr("id");return this.widgetSortable=this.$(".widgets-container").sortable({placeholder:"so-widget-sortable-highlight",connectWith:"#"+t+" .so-cells .cell .widgets-container",tolerance:"pointer",scroll:!1,over:function(t,i){e.row.builder.trigger("widget_sortable_move")},stop:function(t,i){e.row.builder.addHistoryEntry("widget_moved");var s=l(i.item),o=s.data("view"),n=s.closest(".cell").data("view");o.model.moveToCell(n.model,{},s.index()),o.cell=n,o.cell.row.builder.model.refreshPanelsData()},helper:function(e,t){var i=t.clone().css({width:t.outerWidth(),"z-index":1e4,position:"fixed"}).addClass("widget-being-dragged").appendTo("body");return t.outerWidth()>720&&i.animate({"margin-left":e.pageX-t.offset().left-240,width:480},"fast"),i}}),this},refreshSortable:function(){_.isNull(this.widgetSortable)||this.widgetSortable.sortable("refresh")},initResizable:function(){if(!this.row.builder.supports("editRow"))return this;var e,t=this.$(".resize-handle").css("position","absolute"),i=this.row.$el,s=this;return t.draggable({axis:"x",containment:i,start:function(t,i){if(e=s.$el.prev().data("view"),!_.isUndefined(e)){var o=s.$el.clone().appendTo(i.helper).css({position:"absolute",top:"0",width:s.$el.outerWidth(),left:5,height:s.$el.outerHeight()});o.find(".resize-handle").remove();var n=e.$el.clone().appendTo(i.helper).css({position:"absolute",top:"0",width:e.$el.outerWidth(),right:5,height:e.$el.outerHeight()});n.find(".resize-handle").remove(),l(this).data({newCellClone:o,prevCellClone:n})}},drag:function(i,o){var n=s.row.$el.width()+10,a=s.model.get("weight")-(o.position.left+t.outerWidth()/2)/n,r=e.model.get("weight")+(o.position.left+t.outerWidth()/2)/n;l(this).data("newCellClone").css("width",n*a).find(".preview-cell-weight").html(Math.round(1e3*a)/10),l(this).data("prevCellClone").css("width",n*r).find(".preview-cell-weight").html(Math.round(1e3*r)/10)},stop:function(i,o){l(this).data("newCellClone").remove(),l(this).data("prevCellClone").remove();var n=s.row.$el.width()+10,a=s.model.get("weight")-(o.position.left+t.outerWidth()/2)/n,r=e.model.get("weight")+(o.position.left+t.outerWidth()/2)/n;a>.02&&r>.02&&(s.row.builder.addHistoryEntry("cell_resized"),s.model.set("weight",a),e.model.set("weight",r),s.row.resize()),o.helper.css("left",-t.outerWidth()/2),s.row.builder.model.refreshPanelsData()}}),this},onAddWidget:function(e,t,i){i=_.extend({noAnimate:!1},i);var l=new s.view.widget({model:e});l.cell=this,_.isUndefined(e.isDuplicate)&&(e.isDuplicate=!1),l.render({loadForm:e.isDuplicate}),_.isUndefined(i.at)||t.length<=1?l.$el.appendTo(this.$(".widgets-container")):l.$el.insertAfter(this.$(".widgets-container .so-widget").eq(i.at-1)),!1===i.noAnimate&&l.visualCreate(),this.refreshSortable(),this.row.resize()},handleCellClick:function(e){this.row.builder.$el.find(".so-cells .cell").removeClass("cell-selected"),this.row.builder.activeCell!==this||this.model.get("widgets").length?(this.$el.addClass("cell-selected"),this.row.builder.activeCell=this):this.row.builder.activeCell=null},pasteHandler:function(){var e=s.helpers.clipboard.getModel("widget-model");!_.isEmpty(e)&&e instanceof s.model.widget&&(this.row.builder.addHistoryEntry("widget_pasted"),e.cell=this.model,this.model.get("widgets").add(e),this.row.builder.model.refreshPanelsData())},buildContextualMenu:function(e,t){var i=this;t.hasSection("add-widget-below")||t.addSection("add-widget-cell",{sectionTitle:panelsOptions.loc.contextual.add_widget_cell,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){i.row.builder.addHistoryEntry("widget_added");var t=new s.model.widget({class:e});t.cell=i.model,t.cell.get("widgets").add(t),i.row.builder.model.refreshPanelsData()});var l={};this.row.builder.supports("addWidget")&&s.helpers.clipboard.isModel("widget-model")&&(l.paste={title:panelsOptions.loc.contextual.cell_paste_widget}),_.isEmpty(l)||t.addSection("cell-actions",{sectionTitle:panelsOptions.loc.contextual.cell_actions,search:!1},l,function(e){switch(e){case"paste":this.pasteHandler()}this.row.builder.model.refreshPanelsData()}.bind(this)),this.row.buildContextualMenu(e,t)}})},{}],25:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({dialogTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog").html())),dialogTabTemplate:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-dialog-tab").html())),tabbed:!1,rendered:!1,builder:!1,className:"so-panels-dialog-wrapper",dialogClass:"",dialogIcon:"",parentDialog:!1,dialogOpen:!1,editableLabel:!1,events:{"click .so-close":"closeDialog","click .so-nav.so-previous":"navToPrevious","click .so-nav.so-next":"navToNext"},initialize:function(){this.once("open_dialog",this.render),this.once("open_dialog",this.attach),this.once("open_dialog",this.setDialogClass),this.trigger("initialize_dialog",this),_.isUndefined(this.initializeDialog)||this.initializeDialog()},getNextDialog:function(){return null},getPrevDialog:function(){return null},setDialogClass:function(){""!==this.dialogClass&&this.$(".so-panels-dialog").addClass(this.dialogClass)},setBuilder:function(e){return this.builder=e,e.trigger("add_dialog",this,this.builder),this},attach:function(){return this.$el.appendTo("body"),this},parseDialogContent:function(e,t){t=_.extend({cid:this.cid},t);var i=l(_.template(s.helpers.utils.processTemplate(e))(t)),o={title:i.find(".title").html(),buttons:i.find(".buttons").html(),content:i.find(".content").html()};return i.has(".left-sidebar")&&(o.left_sidebar=i.find(".left-sidebar").html()),i.has(".right-sidebar")&&(o.right_sidebar=i.find(".right-sidebar").html()),o},renderDialog:function(e){if(e=_.extend({editableLabel:this.editableLabel,dialogIcon:this.dialogIcon},e),this.$el.html(this.dialogTemplate(e)).hide(),this.$el.data("view",this),this.$el.addClass("so-panels-dialog-wrapper"),!1!==this.parentDialog){var t=this,i=l('<h3 class="so-parent-link"></h3>').html(this.parentDialog.text+'<div class="so-separator"></div>');i.click(function(e){e.preventDefault(),t.closeDialog(),t.parentDialog.openDialog()}),this.$(".so-title-bar").prepend(i)}return this.$(".so-title-bar .so-title-editable").length&&this.initEditableLabel(),this},initTabs:function(){var e=this.$(".so-sidebar-tabs li a");if(0===e.length)return this;var t=this;return e.click(function(e){e.preventDefault();var i=l(this);t.$(".so-sidebar-tabs li").removeClass("tab-active"),t.$(".so-content .so-content-tabs > *").hide(),i.parent().addClass("tab-active");var s=i.attr("href");if(!_.isUndefined(s)&&"#"===s.charAt(0)){var o=s.split("#")[1];t.$(".so-content .so-content-tabs .tab-"+o).show()}t.trigger("tab_click",i)}),this.$(".so-sidebar-tabs li a").first().click(),this},initToolbar:function(){this.$(".so-toolbar .so-buttons .so-toolbar-button").click(function(e){e.preventDefault(),this.trigger("button_click",l(e.currentTarget))}.bind(this)),this.$(".so-toolbar .so-buttons .so-dropdown-button").click(function(e){e.preventDefault();var t=l(e.currentTarget),i=t.siblings(".so-dropdown-links-wrapper");i.is(".hidden")?i.removeClass("hidden"):i.addClass("hidden")}.bind(this)),l("html").click(function(e){this.$(".so-dropdown-links-wrapper").not(".hidden").each(function(t,i){var s=l(i),o=l(e.target);0!==o.length&&(o.is(".so-needs-confirm")&&!o.is(".so-confirmed")||o.is(".so-dropdown-button"))||s.addClass("hidden")})}.bind(this))},initEditableLabel:function(){var e=this.$(".so-title-bar .so-title-editable");e.keypress(function(t){var i="keypress"===t.type&&13===t.keyCode;if(i){var s=l(":tabbable"),o=s.index(e);s.eq(o+1).focus(),window.getSelection().removeAllRanges()}return!i}).blur(function(){var t=e.text().replace(/^\s+|\s+$/gm,"");t!==e.data("original-value").replace(/^\s+|\s+$/gm,"")&&(e.text(t),this.trigger("edit_label",t))}.bind(this)),e.focus(function(){e.data("original-value",e.text()),s.helpers.utils.selectElementContents(this)})},setupDialog:function(){this.openDialog(),this.closeDialog()},refreshDialogNav:function(){this.$(".so-title-bar .so-nav").show().removeClass("so-disabled");var e=this.getNextDialog(),t=this.$(".so-title-bar .so-next"),i=this.getPrevDialog(),s=this.$(".so-title-bar .so-previous");null===e?t.hide():!1===e&&t.addClass("so-disabled"),null===i?s.hide():!1===i&&s.addClass("so-disabled")},openDialog:function(e){e=_.extend({silent:!1},e),e.silent||this.trigger("open_dialog"),this.dialogOpen=!0,this.refreshDialogNav(),s.helpers.pageScroll.lock(),l(window).on("keyup",this.keyboardListen),this.$el.show(),e.silent||(this.trigger("open_dialog_complete"),this.builder.trigger("open_dialog",this),l(document).trigger("open_dialog",this))},closeDialog:function(e){e=_.extend({silent:!1},e),e.silent||this.trigger("close_dialog"),this.dialogOpen=!1,this.$el.hide(),s.helpers.pageScroll.unlock(),l(window).off("keyup",this.keyboardListen),e.silent||(this.trigger("close_dialog_complete"),this.builder.trigger("close_dialog",this))},keyboardListen:function(e){27===e.which&&l(".so-panels-dialog-wrapper .so-close").trigger("click")},navToPrevious:function(){this.closeDialog();var e=this.getPrevDialog();null!==e&&!1!==e&&e.openDialog()},navToNext:function(){this.closeDialog();var e=this.getNextDialog();null!==e&&!1!==e&&e.openDialog()},getFormValues:function(e){_.isUndefined(e)&&(e=".so-content");var t,i=this.$(e),s={};return i.find("[name]").each(function(){var e=l(this);try{var i=/([A-Za-z_]+)\[(.*)\]/.exec(e.attr("name"));if(_.isEmpty(i))return!0;_.isUndefined(i[2])?t=e.attr("name"):(t=i[2].split("]["),t.unshift(i[1])),t=t.map(function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e});var o=s,n=null,a=!!_.isString(e.attr("type"))&&e.attr("type").toLowerCase();if("checkbox"===a)n=e.is(":checked")?""===e.val()||e.val():null;else if("radio"===a){if(!e.is(":checked"))return;n=e.val()}else if("SELECT"===e.prop("tagName")){var r=e.find("option:selected");1===r.length?n=e.find("option:selected").val():r.length>1&&(n=_.map(e.find("option:selected"),function(e,t){return l(e).val()}))}else n=e.val();if(!_.isUndefined(e.data("panels-filter")))switch(e.data("panels-filter")){case"json_parse":try{n=JSON.parse(n)}catch(e){n=""}}if(null!==n)for(var d=0;d<t.length;d++)d===t.length-1?""===t[d]?o.push(n):o[t[d]]=n:(_.isUndefined(o[t[d]])&&(""===t[d+1]?o[t[d]]=[]:o[t[d]]={}),o=o[t[d]])}catch(t){console.log("Field ["+e.attr("name")+"] could not be processed and was skipped - "+t.message)}}),s},setStatusMessage:function(e,t,i){var s=i?'<span class="dashicons dashicons-warning"></span>'+e:e;this.$(".so-toolbar .so-status").html(s),!_.isUndefined(t)&&t?this.$(".so-toolbar .so-status").addClass("so-panels-loading"):this.$(".so-toolbar .so-status").removeClass("so-panels-loading")},setParent:function(e,t){this.parentDialog={text:e,dialog:t}}})},{}],26:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-live-editor").html())),previewScrollTop:0,loadTimes:[],previewFrameId:1,previewUrl:null,previewIframe:null,events:{"click .live-editor-close":"close","click .live-editor-collapse":"collapse","click .live-editor-mode":"mobileToggle"},initialize:function(e){e=_.extend({builder:!1,previewUrl:!1},e),_.isEmpty(e.previewUrl)&&(e.previewUrl=panelsOptions.ajaxurl+"&action=so_panels_live_editor_preview"),this.builder=e.builder,this.previewUrl=e.previewUrl,this.builder.model.on("refresh_panels_data",this.handleRefreshData,this),this.builder.model.on("load_panels_data",this.handleLoadData,this)},render:function(){this.setElement(this.template()),this.$el.hide();var e=this,t=!1;return l(document).mousedown(function(){t=!0}).mouseup(function(){t=!1}),this.$el.on("mouseenter",".so-widget-wrapper",function(){var i=l(this),s=i.data("live-editor-preview-widget");t||void 0===s||!s.length||e.$(".so-preview-overlay").is(":visible")||(e.highlightElement(s),e.scrollToElement(s))}),e.$el.on("mouseleave",".so-widget-wrapper",function(){e.resetHighlights()}),e.builder.on("open_dialog",function(){e.resetHighlights()}),this},attach:function(){this.$el.appendTo("body")},open:function(){if(""===this.$el.html()&&this.render(),0===this.$el.closest("body").length&&this.attach(),s.helpers.pageScroll.lock(),this.$el.is(":visible"))return this;if(this.$el.show(),this.refreshPreview(this.builder.model.getPanelsData()),this.originalContainer=this.builder.$el.parent(),this.builder.$el.appendTo(this.$(".so-live-editor-builder")),this.builder.$(".so-tool-button.so-live-editor").hide(),this.builder.trigger("builder_resize"),"auto-draft"===l("#original_post_status").val()&&!this.autoSaved){var e=this;wp.autosave&&(""===l('#title[name="post_title"]').val()&&l('#title[name="post_title"]').val(panelsOptions.loc.draft).trigger("keydown"),l(document).one("heartbeat-tick.autosave",function(){e.autoSaved=!0,e.refreshPreview(e.builder.model.getPanelsData())}),wp.autosave.server.triggerSave())}},close:function(){if(!this.$el.is(":visible"))return this;this.$el.hide(),s.helpers.pageScroll.unlock(),this.builder.$el.appendTo(this.originalContainer),this.builder.$(".so-tool-button.so-live-editor").show(),this.builder.trigger("builder_resize")},collapse:function(){this.$el.toggleClass("so-collapsed");var e=this.$(".live-editor-collapse span");e.html(e.data(this.$el.hasClass("so-collapsed")?"expand":"collapse"))},highlightElement:function(e){_.isUndefined(this.resetHighlightTimeout)||clearTimeout(this.resetHighlightTimeout),this.previewIframe.contents().find("body").find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return 0===l(this).parents(".so-panel").length}).not(e).addClass("so-panels-faded"),e.removeClass("so-panels-faded").addClass("so-panels-highlighted")},resetHighlights:function(){var e=this.previewIframe.contents().find("body");this.resetHighlightTimeout=setTimeout(function(){e.find(".panel-grid .panel-grid-cell .so-panel").removeClass("so-panels-faded so-panels-highlighted")},100)},scrollToElement:function(e){this.$(".so-preview iframe")[0].contentWindow.liveEditorScrollTo(e)},handleRefreshData:function(e,t){if(!this.$el.is(":visible"))return this;this.refreshPreview(e)},handleLoadData:function(){if(!this.$el.is(":visible"))return this;this.refreshPreview(this.builder.model.getPanelsData())},refreshPreview:function(e){var t=this.loadTimes.length?_.reduce(this.loadTimes,function(e,t){return e+t},0)/this.loadTimes.length:1e3;_.isNull(this.previewIframe)||this.$(".so-preview-overlay").is(":visible")||(this.previewScrollTop=this.previewIframe.contents().scrollTop()),this.$(".so-preview-overlay").show(),this.$(".so-preview-overlay .so-loading-bar").clearQueue().css("width","0%").animate({width:"100%"},parseInt(t)+100),this.postToIframe({live_editor_panels_data:JSON.stringify(e),live_editor_post_ID:this.builder.config.postId},this.previewUrl,this.$(".so-preview")),this.previewIframe.data("load-start",(new Date).getTime())},postToIframe:function(e,t,i){_.isNull(this.previewIframe)||this.previewIframe.remove();var s="siteorigin-panels-live-preview-"+this.previewFrameId;this.previewIframe=l('<iframe src="javascript:false;" />').attr({id:s,name:s}).appendTo(i),this.setupPreviewFrame(this.previewIframe);var o=l('<form id="soPostToPreviewFrame" method="post" />').attr({id:s,target:this.previewIframe.attr("id"),action:t}).appendTo("body");return l.each(e,function(e,t){l('<input type="hidden" />').attr({name:e,value:t}).appendTo(o)}),o.submit().remove(),this.previewFrameId++,this.previewIframe},setupPreviewFrame:function(e){var t=this;e.data("iframeready",!1).on("iframeready",function(){var e=l(this),i=e.contents();if(!e.data("iframeready")){e.data("iframeready",!0),void 0!==e.data("load-start")&&(t.loadTimes.unshift((new Date).getTime()-e.data("load-start")),_.isEmpty(t.loadTimes)||(t.loadTimes=t.loadTimes.slice(0,4))),setTimeout(function(){i.scrollTop(t.previewScrollTop),t.$(".so-preview-overlay").hide()},100);var s=i.find("#pl-"+t.builder.config.postId);s.find(".panel-grid .panel-grid-cell .so-panel").filter(function(){return l(this).closest(".panel-layout").is(s)}).each(function(e,i){var s=l(i),o=t.$(".so-live-editor-builder .so-widget-wrapper").eq(s.data("index"));o.data("live-editor-preview-widget",s),s.css({cursor:"pointer"}).mouseenter(function(){o.parent().addClass("so-hovered"),t.highlightElement(s)}).mouseleave(function(){o.parent().removeClass("so-hovered"),t.resetHighlights()}).click(function(e){e.preventDefault(),o.find(".title h4").click()})}),i.find("a").css({"pointer-events":"none"}).click(function(e){e.preventDefault()})}}).on("load",function(){var e=l(this);e.data("iframeready")||e.trigger("iframeready")})},hasPreviewUrl:function(){return""!==this.$("form.live-editor-form").attr("action")},mobileToggle:function(e){var t=l(e.currentTarget);this.$(".live-editor-mode").not(t).removeClass("so-active"),t.addClass("so-active"),this.$el.removeClass("live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode").addClass("live-editor-"+t.data("mode")+"-mode")}})},{}],27:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-row").html())),events:{"click .so-row-settings":"editSettingsHandler","click .so-row-duplicate":"duplicateHandler","click .so-row-delete":"confirmedDeleteHandler","click .so-row-color":"rowColorChangeHandler"},builder:null,dialog:null,initialize:function(){var e=this.model.get("cells");e.on("add",this.handleCellAdd,this),e.on("remove",this.handleCellRemove,this),this.model.on("reweight_cells",this.resize,this),this.model.on("destroy",this.onModelDestroy,this),this.model.on("visual_destroy",this.visualDestroyModel,this);var t=this;e.each(function(e){t.listenTo(e.get("widgets"),"add",t.resize)}),e.on("add",function(e){t.listenTo(e.get("widgets"),"add",t.resize)},this),this.model.on("change:label",this.onLabelChange,this)},render:function(){var e=this.model.has("color_label")?this.model.get("color_label"):1,t=this.model.has("label")?this.model.get("label"):"";this.setElement(this.template({rowColorLabel:e,rowLabel:t})),this.$el.data("view",this);var i=this;return this.model.get("cells").each(function(e){var t=new s.view.cell({model:e});t.row=i,t.render(),t.$el.appendTo(i.$(".so-cells"))}),this.builder.supports("rowAction")?(this.builder.supports("editRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-settings").parent().remove(),this.$el.addClass("so-row-no-edit")),this.builder.supports("addRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-duplicate").parent().remove(),this.$el.addClass("so-row-no-duplicate")),this.builder.supports("deleteRow")||(this.$(".so-row-toolbar .so-dropdown-links-wrapper .so-row-delete").parent().remove(),this.$el.addClass("so-row-no-delete"))):(this.$(".so-row-toolbar .so-dropdown-wrapper").remove(),this.$el.addClass("so-row-no-actions")),this.builder.supports("moveRow")||(this.$(".so-row-toolbar .so-row-move").remove(),this.$el.addClass("so-row-no-move")),l.trim(this.$(".so-row-toolbar").html()).length||this.$(".so-row-toolbar").remove(),this.builder.on("widget_sortable_move",this.resize,this),this.builder.on("builder_resize",this.resize,this),this.resize(),this},visualCreate:function(){this.$el.hide().fadeIn("fast")},resize:function(e){if(this.$el.is(":visible")){this.$(".so-cells .cell-wrapper").css("min-height",0),this.$(".so-cells .resize-handle").css("height",0);var t=0;this.$(".so-cells .cell").each(function(){t=Math.max(t,l(this).height()),l(this).css("width",100*l(this).data("view").model.get("weight")+"%")}),this.$(".so-cells .cell-wrapper").css("min-height",Math.max(t,63)),this.$(".so-cells .resize-handle").css("height",this.$(".so-cells .cell-wrapper").outerHeight())}},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){this.builder.addHistoryEntry("row_deleted");var e=this;this.$el.fadeOut("normal",function(){e.model.destroy(),e.builder.model.refreshPanelsData()})},onLabelChange:function(e,t){0==this.$(".so-row-label").length?this.$(".so-row-toolbar").prepend('<h3 class="so-row-label">'+t+"</h3>"):this.$(".so-row-label").text(t)},duplicateHandler:function(){this.builder.addHistoryEntry("row_duplicated");var e=this.model.clone(this.builder.model);this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()},copyHandler:function(){s.helpers.clipboard.setModel(this.model)},pasteHandler:function(){var e=s.helpers.clipboard.getModel("row-model");!_.isEmpty(e)&&e instanceof s.model.row&&(this.builder.addHistoryEntry("row_pasted"),e.builder=this.builder.model,this.builder.model.get("rows").add(e,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData())},confirmedDeleteHandler:function(e){var t=l(e.target);if(t.hasClass("dashicons")&&(t=l.parent()),t.hasClass("so-confirmed"))this.visualDestroyModel();else{var i=t.html();t.addClass("so-confirmed").html('<span class="dashicons dashicons-yes"></span>'+panelsOptions.loc.dropdown_confirm),setTimeout(function(){t.removeClass("so-confirmed").html(i)},2500)}},editSettingsHandler:function(){if(this.builder.supports("editRow"))return null===this.dialog&&(this.dialog=new s.dialog.row,this.dialog.setBuilder(this.builder).setRowModel(this.model)),this.dialog.openDialog(),this},deleteHandler:function(){return this.model.destroy(),this},rowColorChangeHandler:function(e){this.$(".so-row-color").removeClass("so-row-color-selected");var t=l(e.target),i=t.data("color-label"),s=this.model.has("color_label")?this.model.get("color_label"):1;t.addClass("so-row-color-selected"),this.$el.removeClass("so-row-color-"+s),this.$el.addClass("so-row-color-"+i),this.model.set("color_label",i)},handleCellAdd:function(e){var t=new s.view.cell({model:e});t.row=this,t.render(),t.$el.appendTo(this.$(".so-cells"))},handleCellRemove:function(e){this.$(".so-cells > .cell").each(function(){var t=l(this).data("view");_.isUndefined(t)||t.model.cid===e.cid&&t.remove()})},buildContextualMenu:function(e,t){for(var i=[],l=1;l<5;l++)i.push({title:l+" "+panelsOptions.loc.contextual.column});this.builder.supports("addRow")&&t.addSection("add-row",{sectionTitle:panelsOptions.loc.contextual.add_row,search:!1},i,function(e){this.builder.addHistoryEntry("row_added");for(var t=Number(e)+1,i=[],l=0;l<t;l++)i.push({weight:100/t});var o=new s.model.row({collection:this.collection}),n=new s.collection.cells(i);n.each(function(e){e.row=o}),o.setCells(n),o.builder=this.builder.model,this.builder.model.get("rows").add(o,{at:this.builder.model.get("rows").indexOf(this.model)+1}),this.builder.model.refreshPanelsData()}.bind(this));var o={};this.builder.supports("editRow")&&(o.edit={title:panelsOptions.loc.contextual.row_edit}),s.helpers.clipboard.canCopyPaste()&&(o.copy={title:panelsOptions.loc.contextual.row_copy},this.builder.supports("addRow")&&s.helpers.clipboard.isModel("row-model")&&(o.paste={title:panelsOptions.loc.contextual.row_paste})),this.builder.supports("addRow")&&(o.duplicate={title:panelsOptions.loc.contextual.row_duplicate}),this.builder.supports("deleteRow")&&(o.delete={title:panelsOptions.loc.contextual.row_delete,confirm:!0}),_.isEmpty(o)||t.addSection("row-actions",{sectionTitle:panelsOptions.loc.contextual.row_actions,search:!1},o,function(e){switch(e){case"edit":this.editSettingsHandler();break;case"copy":this.copyHandler();break;case"paste":this.pasteHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this))}})},{}],28:[function(e,t,i){var s=(window.panels,jQuery);t.exports=Backbone.View.extend({stylesLoaded:!1,initialize:function(){},render:function(e,t,i){if(!_.isUndefined(e)){i=_.extend({builderType:"",dialog:null},i),this.$el.addClass("so-visual-styles so-"+e+"-styles");var l={builderType:i.builderType};return"cell"===e&&(l.index=i.index),s.post(panelsOptions.ajaxurl,{action:"so_panels_style_form",type:e,style:this.model.get("style"),args:JSON.stringify(l),postId:t},function(e){this.$el.html(e),this.setupFields(),this.stylesLoaded=!0,this.trigger("styles_loaded",!_.isEmpty(e)),_.isNull(i.dialog)||i.dialog.trigger("styles_loaded",!_.isEmpty(e))}.bind(this)),this}},attach:function(e){e.append(this.$el)},detach:function(){this.$el.detach()},setupFields:function(){this.$(".style-section-wrapper").each(function(){var e=s(this);e.find(".style-section-head").click(function(t){t.preventDefault(),e.find(".style-section-fields").slideToggle("fast")})}),_.isUndefined(s.fn.wpColorPicker)||(_.isObject(panelsOptions.wpColorPickerOptions.palettes)&&!s.isArray(panelsOptions.wpColorPickerOptions.palettes)&&(panelsOptions.wpColorPickerOptions.palettes=s.map(panelsOptions.wpColorPickerOptions.palettes,function(e){return e})),this.$(".so-wp-color-field").wpColorPicker(panelsOptions.wpColorPickerOptions)),this.$(".style-field-image").each(function(){var e=null,t=s(this);t.find(".so-image-selector").click(function(i){i.preventDefault(),null===e&&(e=wp.media({title:"choose",library:{type:"image"},button:{text:"Done",close:!0}}),e.on("select",function(){var i=e.state().get("selection").first().attributes,s=i.url;if(!_.isUndefined(i.sizes))try{s=i.sizes.thumbnail.url}catch(e){s=i.sizes.full.url}t.find(".current-image").css("background-image","url("+s+")"),t.find("input").val(i.id)})),e.open()}),t.find(".remove-image").click(function(e){e.preventDefault(),t.find(".current-image").css("background-image","none"),t.find("input").val("")})}),this.$(".style-field-measurement").each(function(){var e=s(this),t=e.find('input[type="text"]'),i=e.find("select"),l=e.find('input[type="hidden"]');t.focus(function(){s(this).select()});!function(e){if(""!==e){var o=/(?:([0-9\.,\-]+)(.*))+/,n=l.val().split(" "),a=[];for(var r in n){var d=o.exec(n[r]);_.isNull(d)||_.isUndefined(d[1])||_.isUndefined(d[2])||(a.push(d[1]),i.val(d[2]))}
4
+ 1===t.length?t.val(a.join(" ")):(1===a.length?a=[a[0],a[0],a[0],a[0]]:2===a.length?a=[a[0],a[1],a[0],a[1]]:3===a.length&&(a=[a[0],a[1],a[2],a[1]]),t.each(function(e,t){s(t).val(a[e])}))}}(l.val());var o=function(e){if(1===t.length){var o=t.val().split(" ").filter(function(e){return""!==e}).map(function(e){return e+i.val()}).join(" ");l.val(o)}else{var n=s(e.target),a=[],r=[],d=[];t.each(function(e,t){var i=""!==s(t).val()?parseFloat(s(t).val()):null;a.push(i),null===i?r.push(e):d.push(e)}),3===r.length&&d[0]===t.index(n)&&(t.val(n.val()),a=[n.val(),n.val(),n.val(),n.val()]),JSON.stringify(a)===JSON.stringify([null,null,null,null])?l.val(""):l.val(a.map(function(e){return(null===e?0:e)+i.val()}).join(" "))}};t.change(o),i.change(o)})}})},{}],29:[function(e,t,i){var s=window.panels,l=jQuery;t.exports=Backbone.View.extend({template:_.template(s.helpers.utils.processTemplate(l("#siteorigin-panels-builder-widget").html())),cell:null,dialog:null,events:{"click .widget-edit":"editHandler","click .title h4":"titleClickHandler","click .actions .widget-duplicate":"duplicateHandler","click .actions .widget-delete":"deleteHandler"},initialize:function(){this.model.on("user_edit",this.editHandler,this),this.model.on("user_duplicate",this.duplicateHandler,this),this.model.on("destroy",this.onModelDestroy,this),this.model.on("visual_destroy",this.visualDestroyModel,this),this.model.on("change:values",this.onModelChange,this),this.model.on("change:label",this.onLabelChange,this)},render:function(e){if(e=_.extend({loadForm:!1},e),this.setElement(this.template({title:this.model.getWidgetField("title"),description:this.model.getTitle()})),this.$el.data("view",this),this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")||(this.$(".actions .widget-edit").remove(),this.$el.addClass("so-widget-no-edit")),this.cell.row.builder.supports("addWidget")||(this.$(".actions .widget-duplicate").remove(),this.$el.addClass("so-widget-no-duplicate")),this.cell.row.builder.supports("deleteWidget")||(this.$(".actions .widget-delete").remove(),this.$el.addClass("so-widget-no-delete")),this.cell.row.builder.supports("moveWidget")||this.$el.addClass("so-widget-no-move"),l.trim(this.$(".actions").html()).length||this.$(".actions").remove(),this.model.get("read_only")&&this.$el.addClass("so-widget-read-only"),0===_.size(this.model.get("values"))||e.loadForm){var t=this.getEditDialog();t.once("form_loaded",t.saveWidget,t),t.setupDialog()}return this},visualCreate:function(){this.$el.hide().fadeIn("fast")},getEditDialog:function(){return null===this.dialog&&(this.dialog=new s.dialog.widget({model:this.model}),this.dialog.setBuilder(this.cell.row.builder),this.dialog.widgetView=this),this.dialog},editHandler:function(){this.getEditDialog().openDialog()},titleClickHandler:function(e){return!this.cell.row.builder.supports("editWidget")||this.model.get("read_only")?this:(this.editHandler(),this)},duplicateHandler:function(){this.cell.row.builder.addHistoryEntry("widget_duplicated");var e=this.model.clone(this.model.cell);return this.cell.model.get("widgets").add(e,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData(),this},copyHandler:function(){s.helpers.clipboard.setModel(this.model)},deleteHandler:function(){return this.model.trigger("visual_destroy"),this},onModelChange:function(){this.$(".description").html(this.model.getTitle())},onLabelChange:function(e){this.$(".title > h4").text(e.getWidgetField("title"))},onModelDestroy:function(){this.remove()},visualDestroyModel:function(){this.cell.row.builder.addHistoryEntry("widget_deleted");var e=this;return this.$el.fadeOut("fast",function(){e.cell.row.resize(),e.model.destroy(),e.cell.row.builder.model.refreshPanelsData(),e.remove()}),this},buildContextualMenu:function(e,t){this.cell.row.builder.supports("addWidget")&&t.addSection("add-widget-below",{sectionTitle:panelsOptions.loc.contextual.add_widget_below,searchPlaceholder:panelsOptions.loc.contextual.search_widgets,defaultDisplay:panelsOptions.contextual.default_widgets},panelsOptions.widgets,function(e){this.cell.row.builder.addHistoryEntry("widget_added");var t=new s.model.widget({class:e});t.cell=this.cell.model,this.cell.model.get("widgets").add(t,{at:this.model.collection.indexOf(this.model)+1}),this.cell.row.builder.model.refreshPanelsData()}.bind(this));var i={};this.cell.row.builder.supports("editWidget")&&!this.model.get("read_only")&&(i.edit={title:panelsOptions.loc.contextual.widget_edit}),s.helpers.clipboard.canCopyPaste()&&(i.copy={title:panelsOptions.loc.contextual.widget_copy}),this.cell.row.builder.supports("addWidget")&&(i.duplicate={title:panelsOptions.loc.contextual.widget_duplicate}),this.cell.row.builder.supports("deleteWidget")&&(i.delete={title:panelsOptions.loc.contextual.widget_delete,confirm:!0}),_.isEmpty(i)||t.addSection("widget-actions",{sectionTitle:panelsOptions.loc.contextual.widget_actions,search:!1},i,function(e){switch(e){case"edit":this.editHandler();break;case"copy":this.copyHandler();break;case"duplicate":this.duplicateHandler();break;case"delete":this.visualDestroyModel()}}.bind(this)),this.cell.buildContextualMenu(e,t)}})},{}],30:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.customHtmlWidgets,o=s("<div></div>"),n=t.find(".widget-content:first");n.before(o);var a=new l.CustomHtmlWidgetControl({el:o,syncContainer:n});return a.initializeEditor(),a.editor.codemirror.refresh(),a}};t.exports=l},{}],31:[function(e,t,i){var s=e("./custom-html-widget"),l=e("./media-widget"),o=e("./text-widget"),n={CUSTOM_HTML:"custom_html",MEDIA_AUDIO:"media_audio",MEDIA_GALLERY:"media_gallery",MEDIA_IMAGE:"media_image",MEDIA_VIDEO:"media_video",TEXT:"text",addWidget:function(e,t){var i,n=e.find("> .id_base").val();switch(n){case this.CUSTOM_HTML:i=s;break;case this.MEDIA_AUDIO:case this.MEDIA_GALLERY:case this.MEDIA_IMAGE:case this.MEDIA_VIDEO:i=l;break;case this.TEXT:i=o}i.addWidget(n,e,t)}};t.exports=n},{"./custom-html-widget":30,"./media-widget":32,"./text-widget":33}],32:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.mediaWidgets,o=l.controlConstructors[e];if(o){var n=l.modelConstructors[e]||l.MediaWidgetModel,a=t.find("> .widget-content"),r=s('<div class="media-widget-control"></div>');a.before(r);var d={};a.find(".media-widget-instance-property").each(function(){var e=s(this);d[e.data("property")]=e.val()}),d.widget_id=i;var c=new n(d),h=new o({el:r,syncContainer:a,model:c});return h.render(),h}}};t.exports=l},{}],33:[function(e,t,i){var s=jQuery,l={addWidget:function(e,t,i){var l=wp.textWidgets,o={},n=t.find(".visual");if(n.length>0){if(!n.val())return null;var a=s("<div></div>"),r=t.find(".widget-content:first");r.before(a),o={el:a,syncContainer:r}}else o={el:t};var d=new l.TextWidgetControl(o);return d.initializeEditor(),d}};t.exports=l},{}]},{},[16]);
js/{styling-262.js → styling-263.js} RENAMED
File without changes
js/{styling-262.min.js → styling-263.min.js} RENAMED
File without changes
lang/siteorigin-panels.pot CHANGED
@@ -17,63 +17,63 @@ msgstr ""
17
  "X-Poedit-SearchPathExcluded-0: *.js\n"
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
 
20
- #: tmp/inc/admin-layouts.php:40, tmp/inc/admin-layouts.php:199
21
  msgid "Layouts Directory"
22
  msgstr ""
23
 
24
- #: tmp/inc/admin-layouts.php:163
25
  msgid "Invalid request."
26
  msgstr ""
27
 
28
- #: tmp/inc/admin-layouts.php:178
29
  msgid "Theme Defined Layouts"
30
  msgstr ""
31
 
32
- #: tmp/inc/admin-layouts.php:249
33
  msgid "Clone %s"
34
  msgstr ""
35
 
36
- #: tmp/inc/admin-layouts.php:287
37
  msgid " - Results For:"
38
  msgstr ""
39
 
40
- #: tmp/inc/admin-layouts.php:320
41
  msgid "Missing layout ID or no such layout exists"
42
  msgstr ""
43
 
44
- #: tmp/inc/admin-layouts.php:366
45
  msgid "There was a problem fetching the layout. Please try again later."
46
  msgstr ""
47
 
48
- #: tmp/inc/admin-widget-dialog.php:99, tmp/widgets/widgets.php:164
49
  msgid "Widgets Bundle"
50
  msgstr ""
51
 
52
- #: tmp/inc/admin-widget-dialog.php:114
53
  msgid "Enable more widgets in the 1{Widgets Bundle settings}."
54
  msgstr ""
55
 
56
- #: tmp/inc/admin-widget-dialog.php:120, tmp/inc/data/widgets-bundle.php:11, tmp/inc/data/widgets-bundle.php:23, tmp/inc/data/widgets-bundle.php:35, tmp/inc/data/widgets-bundle.php:47, tmp/inc/data/widgets-bundle.php:59, tmp/inc/data/widgets-bundle.php:71
57
  msgid "SiteOrigin Widgets Bundle"
58
  msgstr ""
59
 
60
- #: tmp/inc/admin-widget-dialog.php:121
61
  msgid "Install the 1{Widgets Bundle} to get extra widgets."
62
  msgstr ""
63
 
64
- #: tmp/inc/admin-widget-dialog.php:129
65
  msgid "Page Builder Widgets"
66
  msgstr ""
67
 
68
- #: tmp/inc/admin-widget-dialog.php:137
69
  msgid "You can enable the legacy (PB) widgets in the 1{Page Builder settings}."
70
  msgstr ""
71
 
72
- #: tmp/inc/admin-widget-dialog.php:145
73
  msgid "WordPress Widgets"
74
  msgstr ""
75
 
76
- #: tmp/inc/admin-widget-dialog.php:185, tmp/inc/settings.php:322
77
  msgid "Recommended Widgets"
78
  msgstr ""
79
 
@@ -85,387 +85,387 @@ msgstr ""
85
  msgid "Installing %s"
86
  msgstr ""
87
 
88
- #: tmp/inc/admin.php:126
89
  msgid "Support Forum"
90
  msgstr ""
91
 
92
- #: tmp/inc/admin.php:127
93
  msgid "Newsletter"
94
  msgstr ""
95
 
96
- #: tmp/inc/admin.php:130, tmp/tpl/js-templates.php:44
97
  msgid "Addons"
98
  msgstr ""
99
 
100
- #: tmp/inc/admin.php:143, tmp/inc/admin.php:507, tmp/inc/admin.php:1018, tmp/inc/admin.php:1023, tmp/inc/settings.php:195, tmp/tpl/js-templates.php:200
101
  msgid "Page Builder"
102
  msgstr ""
103
 
104
- #: tmp/inc/admin.php:279
105
  msgid "All Widgets"
106
  msgstr ""
107
 
108
- #: tmp/inc/admin.php:305
109
  msgid "Missing Widget"
110
  msgstr ""
111
 
112
- #: tmp/inc/admin.php:306
113
  msgid "Page Builder doesn't know about this widget."
114
  msgstr ""
115
 
116
- #: tmp/inc/admin.php:310
117
  msgid "%d seconds"
118
  msgstr ""
119
 
120
- #: tmp/inc/admin.php:312
121
  msgid "%d minutes"
122
  msgstr ""
123
 
124
- #: tmp/inc/admin.php:314
125
  msgid "%d hours"
126
  msgstr ""
127
 
128
- #: tmp/inc/admin.php:317
129
  msgid "%d second"
130
  msgstr ""
131
 
132
- #: tmp/inc/admin.php:319
133
  msgid "%d minute"
134
  msgstr ""
135
 
136
- #: tmp/inc/admin.php:321
137
  msgid "%d hour"
138
  msgstr ""
139
 
140
- #: tmp/inc/admin.php:324
141
  msgid "%s before"
142
  msgstr ""
143
 
144
- #: tmp/inc/admin.php:325
145
  msgid "Now"
146
  msgstr ""
147
 
148
- #: tmp/inc/admin.php:329
149
  msgid "Current"
150
  msgstr ""
151
 
152
- #: tmp/inc/admin.php:330
153
  msgid "Original"
154
  msgstr ""
155
 
156
- #: tmp/inc/admin.php:331
157
  msgid "Version restored"
158
  msgstr ""
159
 
160
- #: tmp/inc/admin.php:332
161
  msgid "Converted to editor"
162
  msgstr ""
163
 
164
- #: tmp/inc/admin.php:336
165
  msgid "Widget deleted"
166
  msgstr ""
167
 
168
- #: tmp/inc/admin.php:338
169
  msgid "Widget added"
170
  msgstr ""
171
 
172
- #: tmp/inc/admin.php:340
173
  msgid "Widget edited"
174
  msgstr ""
175
 
176
- #: tmp/inc/admin.php:342
177
  msgid "Widget duplicated"
178
  msgstr ""
179
 
180
- #: tmp/inc/admin.php:344
181
  msgid "Widget moved"
182
  msgstr ""
183
 
184
- #: tmp/inc/admin.php:348
185
  msgid "Row deleted"
186
  msgstr ""
187
 
188
- #: tmp/inc/admin.php:350
189
  msgid "Row added"
190
  msgstr ""
191
 
192
- #: tmp/inc/admin.php:352
193
  msgid "Row edited"
194
  msgstr ""
195
 
196
- #: tmp/inc/admin.php:354
197
  msgid "Row moved"
198
  msgstr ""
199
 
200
- #: tmp/inc/admin.php:356
201
  msgid "Row duplicated"
202
  msgstr ""
203
 
204
- #: tmp/inc/admin.php:358
205
  msgid "Row pasted"
206
  msgstr ""
207
 
208
- #: tmp/inc/admin.php:361
209
  msgid "Cell resized"
210
  msgstr ""
211
 
212
- #: tmp/inc/admin.php:364
213
  msgid "Prebuilt layout loaded"
214
  msgstr ""
215
 
216
- #: tmp/inc/admin.php:368
217
  msgid "Loading prebuilt layout"
218
  msgstr ""
219
 
220
- #: tmp/inc/admin.php:369
221
  msgid "Would you like to copy this editor's existing content to Page Builder?"
222
  msgstr ""
223
 
224
- #: tmp/inc/admin.php:370
225
  msgid "Would you like to clear your Page Builder content and revert to using the standard visual editor?"
226
  msgstr ""
227
 
228
- #: tmp/inc/admin.php:372
229
  msgid "Layout Builder Widget"
230
  msgstr ""
231
 
232
- #: tmp/inc/admin.php:374, tmp/tpl/js-templates.php:104, tmp/tpl/js-templates.php:425
233
  msgid "Are you sure?"
234
  msgstr ""
235
 
236
- #: tmp/inc/admin.php:376
237
  msgid "%s is ready to insert."
238
  msgstr ""
239
 
240
- #: tmp/inc/admin.php:380
241
  msgid "Add Widget Below"
242
  msgstr ""
243
 
244
- #: tmp/inc/admin.php:381
245
  msgid "Add Widget to Cell"
246
  msgstr ""
247
 
248
- #: tmp/inc/admin.php:382, tmp/tpl/js-templates.php:227
249
  msgid "Search Widgets"
250
  msgstr ""
251
 
252
- #: tmp/inc/admin.php:384, tmp/tpl/js-templates.php:17, tmp/tpl/js-templates.php:19
253
  msgid "Add Row"
254
  msgstr ""
255
 
256
- #: tmp/inc/admin.php:385
257
  msgid "Column"
258
  msgstr ""
259
 
260
- #: tmp/inc/admin.php:387
261
  msgid "Cell Actions"
262
  msgstr ""
263
 
264
- #: tmp/inc/admin.php:388
265
  msgid "Paste Widget"
266
  msgstr ""
267
 
268
- #: tmp/inc/admin.php:390
269
  msgid "Widget Actions"
270
  msgstr ""
271
 
272
- #: tmp/inc/admin.php:391
273
  msgid "Edit Widget"
274
  msgstr ""
275
 
276
- #: tmp/inc/admin.php:392
277
  msgid "Duplicate Widget"
278
  msgstr ""
279
 
280
- #: tmp/inc/admin.php:393
281
  msgid "Delete Widget"
282
  msgstr ""
283
 
284
- #: tmp/inc/admin.php:394
285
  msgid "Copy Widget"
286
  msgstr ""
287
 
288
- #: tmp/inc/admin.php:395
289
  msgid "Paste Widget Below"
290
  msgstr ""
291
 
292
- #: tmp/inc/admin.php:397
293
  msgid "Row Actions"
294
  msgstr ""
295
 
296
- #: tmp/inc/admin.php:398, tmp/tpl/js-templates.php:102
297
  msgid "Edit Row"
298
  msgstr ""
299
 
300
- #: tmp/inc/admin.php:399, tmp/tpl/js-templates.php:103
301
  msgid "Duplicate Row"
302
  msgstr ""
303
 
304
- #: tmp/inc/admin.php:400, tmp/tpl/js-templates.php:104
305
  msgid "Delete Row"
306
  msgstr ""
307
 
308
- #: tmp/inc/admin.php:401
309
  msgid "Copy Row"
310
  msgstr ""
311
 
312
- #: tmp/inc/admin.php:402
313
  msgid "Paste Row"
314
  msgstr ""
315
 
316
- #: tmp/inc/admin.php:404
317
  msgid "Draft"
318
  msgstr ""
319
 
320
- #: tmp/inc/admin.php:405
321
  msgid "Untitled"
322
  msgstr ""
323
 
324
- #: tmp/inc/admin.php:407
325
  msgid "New Row"
326
  msgstr ""
327
 
328
- #: tmp/inc/admin.php:408, tmp/inc/admin.php:416, tmp/inc/styles.php:183, tmp/tpl/js-templates.php:69
329
  msgid "Row"
330
  msgstr ""
331
 
332
- #: tmp/inc/admin.php:411
333
  msgid "Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements."
334
  msgstr ""
335
 
336
- #: tmp/inc/admin.php:412
337
  msgid "Add a {{%= items[0] %}} to get started."
338
  msgstr ""
339
 
340
- #: tmp/inc/admin.php:413
341
  msgid "Add a {{%= items[0] %}} or {{%= items[1] %}} to get started."
342
  msgstr ""
343
 
344
- #: tmp/inc/admin.php:414
345
  msgid "Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started."
346
  msgstr ""
347
 
348
- #: tmp/inc/admin.php:415, tmp/inc/styles.php:316, tmp/tpl/js-templates.php:68
349
  msgid "Widget"
350
  msgstr ""
351
 
352
- #: tmp/inc/admin.php:417, tmp/tpl/js-templates.php:70
353
  msgid "Prebuilt Layout"
354
  msgstr ""
355
 
356
- #: tmp/inc/admin.php:419
357
  msgid "Read our %s if you need help."
358
  msgstr ""
359
 
360
- #: tmp/inc/admin.php:420, tmp/tpl/js-templates.php:71
361
  msgid "documentation"
362
  msgstr ""
363
 
364
- #: tmp/inc/admin.php:429
365
  msgid "Page Builder layouts"
366
  msgstr ""
367
 
368
- #: tmp/inc/admin.php:430
369
  msgid "Error uploading or importing file."
370
  msgstr ""
371
 
372
- #: tmp/inc/admin.php:588, tmp/inc/home.php:26
373
  msgid "Home Page"
374
  msgstr ""
375
 
376
- #: tmp/inc/admin.php:682
377
  msgid "Untitled Widget"
378
  msgstr ""
379
 
380
- #: tmp/inc/admin.php:847
381
  msgid "You need to install 1{%1$s} to use the widget 2{%2$s}."
382
  msgstr ""
383
 
384
- #: tmp/inc/admin.php:853
385
  msgid "Save and reload this page to start using the widget after you've installed it."
386
  msgstr ""
387
 
388
- #: tmp/inc/admin.php:869
389
  msgid "The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help."
390
  msgstr ""
391
 
392
- #: tmp/inc/admin.php:1035
393
  msgid "%s Widgets"
394
  msgstr ""
395
 
396
- #: tmp/inc/admin.php:1081
397
  msgid "12 Page Builder Tips"
398
  msgstr ""
399
 
400
- #: tmp/inc/admin.php:1084
401
  msgid "Sign up to our newsletter and we'll send you this free Page Builder video course."
402
  msgstr ""
403
 
404
- #: tmp/inc/admin.php:1085
405
  msgid "12 tips that'll help you get the most out of Page Builder."
406
  msgstr ""
407
 
408
- #: tmp/inc/admin.php:1086
409
  msgid "Watch the video to find out more, then sign up below to get started."
410
  msgstr ""
411
 
412
- #: tmp/inc/admin.php:1087, tmp/inc/admin.php:1097
413
  msgid "We'll email you a confirmation. You can unsubscribe at any time."
414
  msgstr ""
415
 
416
- #: tmp/inc/admin.php:1091
417
  msgid "Free Page Builder Addons"
418
  msgstr ""
419
 
420
- #: tmp/inc/admin.php:1094
421
  msgid "The free animations addon allows you to add beautiful animations to Page Builder elements."
422
  msgstr ""
423
 
424
- #: tmp/inc/admin.php:1095
425
  msgid "Sign up to our newsletter and we'll send you the addon as a free gift."
426
  msgstr ""
427
 
428
- #: tmp/inc/admin.php:1096
429
  msgid "Plus, we'll send you even more powerful addons, for as long as you're subscribed."
430
  msgstr ""
431
 
432
- #: tmp/inc/admin.php:1112
433
  msgid "Watch Intro Video"
434
  msgstr ""
435
 
436
- #: tmp/inc/admin.php:1113
437
  msgid "Loaded from Vimeo Servers"
438
  msgstr ""
439
 
440
- #: tmp/inc/admin.php:1114
441
  msgid "Please enter a valid email address."
442
  msgstr ""
443
 
444
- #: tmp/inc/admin.php:1116
445
  msgid "Your Name"
446
  msgstr ""
447
 
448
- #: tmp/inc/admin.php:1117
449
  msgid "Your Email"
450
  msgstr ""
451
 
452
- #: tmp/inc/admin.php:1118
453
  msgid "Sign Up"
454
  msgstr ""
455
 
456
- #: tmp/inc/admin.php:1119, tmp/tpl/js-templates.php:239
457
  msgid "Close"
458
  msgstr ""
459
 
460
- #: tmp/inc/admin.php:1130
461
  msgid "Get a lightbox addon for SiteOrigin widgets"
462
  msgstr ""
463
 
464
- #: tmp/inc/admin.php:1134
465
  msgid "Get the row, cell and widget animations addon"
466
  msgstr ""
467
 
468
- #: tmp/inc/admin.php:1138
469
  msgid "Get premium email support for SiteOrigin Page Builder"
470
  msgstr ""
471
 
@@ -525,223 +525,223 @@ msgstr ""
525
  msgid "Page Builder Content"
526
  msgstr ""
527
 
528
- #: tmp/inc/settings.php:195, tmp/settings/tpl/settings.php:9
529
  msgid "SiteOrigin Page Builder"
530
  msgstr ""
531
 
532
- #: tmp/inc/settings.php:222
533
  msgid "Page Builder Settings"
534
  msgstr ""
535
 
536
- #: tmp/inc/settings.php:238
537
  msgid "General"
538
  msgstr ""
539
 
540
- #: tmp/inc/settings.php:244
541
  msgid "Post Types"
542
  msgstr ""
543
 
544
- #: tmp/inc/settings.php:246
545
  msgid "The post types to use Page Builder on."
546
  msgstr ""
547
 
548
- #: tmp/inc/settings.php:251
549
  msgid "Live Editor Quick Link"
550
  msgstr ""
551
 
552
- #: tmp/inc/settings.php:252
553
  msgid "Display a Live Editor button in the admin bar."
554
  msgstr ""
555
 
556
- #: tmp/inc/settings.php:257
557
  msgid "Display Widget Count"
558
  msgstr ""
559
 
560
- #: tmp/inc/settings.php:258
561
  msgid "Display a widget count in the admin lists of posts/pages where you're using Page Builder."
562
  msgstr ""
563
 
564
- #: tmp/inc/settings.php:263
565
  msgid "Limit Parallax Motion"
566
  msgstr ""
567
 
568
- #: tmp/inc/settings.php:264
569
  msgid "How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect."
570
  msgstr ""
571
 
572
- #: tmp/inc/settings.php:269
573
  msgid "Sidebars Emulator"
574
  msgstr ""
575
 
576
- #: tmp/inc/settings.php:270
577
  msgid "Page Builder will create an emulated sidebar, that contains all widgets in the page."
578
  msgstr ""
579
 
580
- #: tmp/inc/settings.php:275
581
  msgid "Upgrade Teaser"
582
  msgstr ""
583
 
584
- #: tmp/inc/settings.php:277
585
  msgid "Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar."
586
  msgstr ""
587
 
588
- #: tmp/inc/settings.php:285
589
  msgid "Page Builder Learning"
590
  msgstr ""
591
 
592
- #: tmp/inc/settings.php:286
593
  msgid "Display buttons for Page Builder learning."
594
  msgstr ""
595
 
596
- #: tmp/inc/settings.php:291
597
  msgid "Default To Page Builder Interface"
598
  msgstr ""
599
 
600
- #: tmp/inc/settings.php:292
601
  msgid "New posts/pages that you create will start with the Page Builder loaded."
602
  msgstr ""
603
 
604
- #: tmp/inc/settings.php:298
605
  msgid "Widgets"
606
  msgstr ""
607
 
608
- #: tmp/inc/settings.php:304
609
  msgid "Widget Title HTML"
610
  msgstr ""
611
 
612
- #: tmp/inc/settings.php:305
613
  msgid "The HTML used for widget titles. {{title}} is replaced with the widget title."
614
  msgstr ""
615
 
616
- #: tmp/inc/settings.php:310
617
  msgid "Add Widget Class"
618
  msgstr ""
619
 
620
- #: tmp/inc/settings.php:311
621
  msgid "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts."
622
  msgstr ""
623
 
624
- #: tmp/inc/settings.php:316
625
  msgid "Legacy Bundled Widgets"
626
  msgstr ""
627
 
628
- #: tmp/inc/settings.php:317
629
  msgid "Load legacy widgets from Page Builder 1."
630
  msgstr ""
631
 
632
- #: tmp/inc/settings.php:323
633
  msgid "Display recommend widgets in Page Builder add widget dialog."
634
  msgstr ""
635
 
636
- #: tmp/inc/settings.php:329, tmp/inc/styles-admin.php:78
637
  msgid "Layout"
638
  msgstr ""
639
 
640
- #: tmp/inc/settings.php:337
641
  msgid "Responsive Layout"
642
  msgstr ""
643
 
644
- #: tmp/inc/settings.php:338
645
  msgid "Collapse widgets, rows and columns on mobile devices."
646
  msgstr ""
647
 
648
- #: tmp/inc/settings.php:343
649
  msgid "Use Tablet Layout"
650
  msgstr ""
651
 
652
- #: tmp/inc/settings.php:344
653
  msgid "Collapses columns differently on tablet devices."
654
  msgstr ""
655
 
656
- #: tmp/inc/settings.php:350
657
  msgid "Detect older browsers"
658
  msgstr ""
659
 
660
- #: tmp/inc/settings.php:351
661
  msgid "Never"
662
  msgstr ""
663
 
664
- #: tmp/inc/settings.php:352
665
  msgid "Always"
666
  msgstr ""
667
 
668
- #: tmp/inc/settings.php:354
669
  msgid "Use Legacy Layout Engine"
670
  msgstr ""
671
 
672
- #: tmp/inc/settings.php:355
673
  msgid "The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers."
674
  msgstr ""
675
 
676
- #: tmp/inc/settings.php:361
677
  msgid "Tablet Width"
678
  msgstr ""
679
 
680
- #: tmp/inc/settings.php:362
681
  msgid "Device width, in pixels, to collapse into a tablet view ."
682
  msgstr ""
683
 
684
- #: tmp/inc/settings.php:368
685
  msgid "Mobile Width"
686
  msgstr ""
687
 
688
- #: tmp/inc/settings.php:369
689
  msgid "Device width, in pixels, to collapse into a mobile view ."
690
  msgstr ""
691
 
692
- #: tmp/inc/settings.php:375
693
  msgid "Row/Widget Bottom Margin"
694
  msgstr ""
695
 
696
- #: tmp/inc/settings.php:376
697
  msgid "Default margin below rows and widgets."
698
  msgstr ""
699
 
700
- #: tmp/inc/settings.php:381
701
  msgid "Last Row With Margin"
702
  msgstr ""
703
 
704
- #: tmp/inc/settings.php:382
705
  msgid "Allow margin in last row."
706
  msgstr ""
707
 
708
- #: tmp/inc/settings.php:388
709
  msgid "Row Gutter"
710
  msgstr ""
711
 
712
- #: tmp/inc/settings.php:389
713
  msgid "Default spacing between columns in each row."
714
  msgstr ""
715
 
716
- #: tmp/inc/settings.php:395
717
  msgid "Full Width Container"
718
  msgstr ""
719
 
720
- #: tmp/inc/settings.php:396
721
  msgid "The container used for the full width layout."
722
  msgstr ""
723
 
724
- #: tmp/inc/settings.php:403
725
  msgid "Content"
726
  msgstr ""
727
 
728
- #: tmp/inc/settings.php:409
729
  msgid "Copy Content"
730
  msgstr ""
731
 
732
- #: tmp/inc/settings.php:410
733
  msgid "Copy content from Page Builder to post content."
734
  msgstr ""
735
 
736
- #: tmp/inc/settings.php:415
737
  msgid "Copy Styles"
738
  msgstr ""
739
 
740
- #: tmp/inc/settings.php:416
741
  msgid "Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated."
742
  msgstr ""
743
 
744
- #: tmp/inc/settings.php:463, tmp/inc/styles-admin.php:248
745
  msgid "Enabled"
746
  msgstr ""
747
 
@@ -1173,15 +1173,15 @@ msgstr ""
1173
  msgid "Save Settings"
1174
  msgstr ""
1175
 
1176
- #: tmp/siteorigin-panels.php:305
1177
  msgid "Read More"
1178
  msgstr ""
1179
 
1180
- #: tmp/siteorigin-panels.php:365
1181
  msgid "Edit Home Page"
1182
  msgstr ""
1183
 
1184
- #: tmp/siteorigin-panels.php:385, tmp/tpl/js-templates.php:34, tmp/tpl/js-templates.php:36
1185
  msgid "Live Editor"
1186
  msgstr ""
1187
 
@@ -1221,183 +1221,183 @@ msgstr ""
1221
  msgid "Read the 1{full documentation} on SiteOrigin. Ask a question on our 2{support forum} if you need help and sign up to 3{our newsletter} to stay up to date with future developments."
1222
  msgstr ""
1223
 
1224
- #: tmp/tpl/js-templates.php:12, tmp/tpl/js-templates.php:14
1225
  msgid "Add Widget"
1226
  msgstr ""
1227
 
1228
- #: tmp/tpl/js-templates.php:22, tmp/tpl/js-templates.php:390
1229
  msgid "Prebuilt Layouts"
1230
  msgstr ""
1231
 
1232
- #: tmp/tpl/js-templates.php:24
1233
  msgid "Layouts"
1234
  msgstr ""
1235
 
1236
- #: tmp/tpl/js-templates.php:29
1237
  msgid "Edit History"
1238
  msgstr ""
1239
 
1240
- #: tmp/tpl/js-templates.php:31
1241
  msgid "History"
1242
  msgstr ""
1243
 
1244
- #: tmp/tpl/js-templates.php:42
1245
  msgid "Page Builder Addons"
1246
  msgstr ""
1247
 
1248
- #: tmp/tpl/js-templates.php:49
1249
  msgid "Learn Page Builder"
1250
  msgstr ""
1251
 
1252
- #: tmp/tpl/js-templates.php:51
1253
  msgid "Learn"
1254
  msgstr ""
1255
 
1256
- #: tmp/tpl/js-templates.php:55
1257
  msgid "Revert to Editor"
1258
  msgstr ""
1259
 
1260
- #: tmp/tpl/js-templates.php:67
1261
  msgid "Add a %s, %s or %s to get started. Read our %s if you need help."
1262
  msgstr ""
1263
 
1264
- #: tmp/tpl/js-templates.php:78
1265
  msgid "Pro Tip"
1266
  msgstr ""
1267
 
1268
- #: tmp/tpl/js-templates.php:148
1269
  msgid "Edit"
1270
  msgstr ""
1271
 
1272
- #: tmp/tpl/js-templates.php:149, tmp/tpl/js-templates.php:271, tmp/tpl/js-templates.php:356
1273
  msgid "Duplicate"
1274
  msgstr ""
1275
 
1276
- #: tmp/tpl/js-templates.php:150, tmp/tpl/js-templates.php:270, tmp/tpl/js-templates.php:355
1277
  msgid "Delete"
1278
  msgstr ""
1279
 
1280
- #: tmp/tpl/js-templates.php:209, tmp/tpl/js-templates.php:274, tmp/tpl/js-templates.php:363, tmp/tpl/js-templates.php:557
1281
  msgid "Done"
1282
  msgstr ""
1283
 
1284
- #: tmp/tpl/js-templates.php:223
1285
  msgid "Add New Widget %s"
1286
  msgstr ""
1287
 
1288
- #: tmp/tpl/js-templates.php:324
1289
  msgid "Left to Right"
1290
  msgstr ""
1291
 
1292
- #: tmp/tpl/js-templates.php:325
1293
  msgid "Right to Left"
1294
  msgstr ""
1295
 
1296
- #: tmp/tpl/js-templates.php:336
1297
  msgid "1{Set row layout}: %1$s columns with a ratio of %2$s going from %3$s"
1298
  msgstr ""
1299
 
1300
- #: tmp/tpl/js-templates.php:342
1301
  msgid "Set"
1302
  msgstr ""
1303
 
1304
- #: tmp/tpl/js-templates.php:361, tmp/tpl/js-templates.php:419
1305
  msgid "Insert"
1306
  msgstr ""
1307
 
1308
- #: tmp/tpl/js-templates.php:381
1309
  msgid "Page Builder Layouts"
1310
  msgstr ""
1311
 
1312
- #: tmp/tpl/js-templates.php:385
1313
  msgid "Search"
1314
  msgstr ""
1315
 
1316
- #: tmp/tpl/js-templates.php:400
1317
  msgid "Import/Export"
1318
  msgstr ""
1319
 
1320
- #: tmp/tpl/js-templates.php:407
1321
  msgid "Clone: %s"
1322
  msgstr ""
1323
 
1324
- #: tmp/tpl/js-templates.php:423
1325
  msgid "Insert after"
1326
  msgstr ""
1327
 
1328
- #: tmp/tpl/js-templates.php:424
1329
  msgid "Insert before"
1330
  msgstr ""
1331
 
1332
- #: tmp/tpl/js-templates.php:425
1333
  msgid "Replace current"
1334
  msgstr ""
1335
 
1336
- #: tmp/tpl/js-templates.php:436
1337
  msgid "Do you want to browse the Prebuilt Layouts directory?"
1338
  msgstr ""
1339
 
1340
- #: tmp/tpl/js-templates.php:437
1341
  msgid "Enable"
1342
  msgstr ""
1343
 
1344
- #: tmp/tpl/js-templates.php:450
1345
  msgid "Your search didn't return any results"
1346
  msgstr ""
1347
 
1348
- #: tmp/tpl/js-templates.php:478
1349
  msgid "Previous"
1350
  msgstr ""
1351
 
1352
- #: tmp/tpl/js-templates.php:479
1353
  msgid "Next"
1354
  msgstr ""
1355
 
1356
- #: tmp/tpl/js-templates.php:489
1357
  msgid "Drop import file here"
1358
  msgstr ""
1359
 
1360
- #: tmp/tpl/js-templates.php:490
1361
  msgid "Or"
1362
  msgstr ""
1363
 
1364
- #: tmp/tpl/js-templates.php:493
1365
  msgid "Select Import File"
1366
  msgstr ""
1367
 
1368
- #: tmp/tpl/js-templates.php:507
1369
  msgid "Download Layout"
1370
  msgstr ""
1371
 
1372
- #: tmp/tpl/js-templates.php:518
1373
  msgid "Page Builder Change History"
1374
  msgstr ""
1375
 
1376
- #: tmp/tpl/js-templates.php:533
1377
  msgid "Restore Version"
1378
  msgstr ""
1379
 
1380
- #: tmp/tpl/js-templates.php:551, tmp/tpl/js-templates.php:552
1381
  msgid "Collapse"
1382
  msgstr ""
1383
 
1384
- #: tmp/tpl/js-templates.php:551
1385
  msgid "Expand"
1386
  msgstr ""
1387
 
1388
- #: tmp/tpl/js-templates.php:559
1389
  msgid "Toggle desktop mode"
1390
  msgstr ""
1391
 
1392
- #: tmp/tpl/js-templates.php:562
1393
  msgid "Toggle tablet mode"
1394
  msgstr ""
1395
 
1396
- #: tmp/tpl/js-templates.php:565
1397
  msgid "Toggle mobile mode"
1398
  msgstr ""
1399
 
1400
- #: tmp/tpl/js-templates.php:604
1401
  msgid "No Results"
1402
  msgstr ""
1403
 
17
  "X-Poedit-SearchPathExcluded-0: *.js\n"
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
 
20
+ #: tmp/inc/admin-layouts.php:79, tmp/inc/admin-layouts.php:405
21
  msgid "Layouts Directory"
22
  msgstr ""
23
 
24
+ #: tmp/inc/admin-layouts.php:333
25
  msgid "Invalid request."
26
  msgstr ""
27
 
28
+ #: tmp/inc/admin-layouts.php:363
29
  msgid "Theme Defined Layouts"
30
  msgstr ""
31
 
32
+ #: tmp/inc/admin-layouts.php:505
33
  msgid "Clone %s"
34
  msgstr ""
35
 
36
+ #: tmp/inc/admin-layouts.php:581
37
  msgid " - Results For:"
38
  msgstr ""
39
 
40
+ #: tmp/inc/admin-layouts.php:647
41
  msgid "Missing layout ID or no such layout exists"
42
  msgstr ""
43
 
44
+ #: tmp/inc/admin-layouts.php:739
45
  msgid "There was a problem fetching the layout. Please try again later."
46
  msgstr ""
47
 
48
+ #: tmp/inc/admin-widget-dialog.php:197, tmp/widgets/widgets.php:164
49
  msgid "Widgets Bundle"
50
  msgstr ""
51
 
52
+ #: tmp/inc/admin-widget-dialog.php:227
53
  msgid "Enable more widgets in the 1{Widgets Bundle settings}."
54
  msgstr ""
55
 
56
+ #: tmp/inc/admin-widget-dialog.php:239, tmp/inc/data/widgets-bundle.php:11, tmp/inc/data/widgets-bundle.php:23, tmp/inc/data/widgets-bundle.php:35, tmp/inc/data/widgets-bundle.php:47, tmp/inc/data/widgets-bundle.php:59, tmp/inc/data/widgets-bundle.php:71
57
  msgid "SiteOrigin Widgets Bundle"
58
  msgstr ""
59
 
60
+ #: tmp/inc/admin-widget-dialog.php:241
61
  msgid "Install the 1{Widgets Bundle} to get extra widgets."
62
  msgstr ""
63
 
64
+ #: tmp/inc/admin-widget-dialog.php:257
65
  msgid "Page Builder Widgets"
66
  msgstr ""
67
 
68
+ #: tmp/inc/admin-widget-dialog.php:273
69
  msgid "You can enable the legacy (PB) widgets in the 1{Page Builder settings}."
70
  msgstr ""
71
 
72
+ #: tmp/inc/admin-widget-dialog.php:289
73
  msgid "WordPress Widgets"
74
  msgstr ""
75
 
76
+ #: tmp/inc/admin-widget-dialog.php:369, tmp/inc/settings.php:643
77
  msgid "Recommended Widgets"
78
  msgstr ""
79
 
85
  msgid "Installing %s"
86
  msgstr ""
87
 
88
+ #: tmp/inc/admin.php:251
89
  msgid "Support Forum"
90
  msgstr ""
91
 
92
+ #: tmp/inc/admin.php:253
93
  msgid "Newsletter"
94
  msgstr ""
95
 
96
+ #: tmp/inc/admin.php:259, tmp/tpl/js-templates.php:87
97
  msgid "Addons"
98
  msgstr ""
99
 
100
+ #: tmp/inc/admin.php:285, tmp/inc/admin.php:1013, tmp/inc/admin.php:2035, tmp/inc/admin.php:2045, tmp/inc/settings.php:389, tmp/tpl/js-templates.php:399
101
  msgid "Page Builder"
102
  msgstr ""
103
 
104
+ #: tmp/inc/admin.php:557
105
  msgid "All Widgets"
106
  msgstr ""
107
 
108
+ #: tmp/inc/admin.php:609
109
  msgid "Missing Widget"
110
  msgstr ""
111
 
112
+ #: tmp/inc/admin.php:611
113
  msgid "Page Builder doesn't know about this widget."
114
  msgstr ""
115
 
116
+ #: tmp/inc/admin.php:619
117
  msgid "%d seconds"
118
  msgstr ""
119
 
120
+ #: tmp/inc/admin.php:623
121
  msgid "%d minutes"
122
  msgstr ""
123
 
124
+ #: tmp/inc/admin.php:627
125
  msgid "%d hours"
126
  msgstr ""
127
 
128
+ #: tmp/inc/admin.php:633
129
  msgid "%d second"
130
  msgstr ""
131
 
132
+ #: tmp/inc/admin.php:637
133
  msgid "%d minute"
134
  msgstr ""
135
 
136
+ #: tmp/inc/admin.php:641
137
  msgid "%d hour"
138
  msgstr ""
139
 
140
+ #: tmp/inc/admin.php:647
141
  msgid "%s before"
142
  msgstr ""
143
 
144
+ #: tmp/inc/admin.php:649
145
  msgid "Now"
146
  msgstr ""
147
 
148
+ #: tmp/inc/admin.php:657
149
  msgid "Current"
150
  msgstr ""
151
 
152
+ #: tmp/inc/admin.php:659
153
  msgid "Original"
154
  msgstr ""
155
 
156
+ #: tmp/inc/admin.php:661
157
  msgid "Version restored"
158
  msgstr ""
159
 
160
+ #: tmp/inc/admin.php:663
161
  msgid "Converted to editor"
162
  msgstr ""
163
 
164
+ #: tmp/inc/admin.php:671
165
  msgid "Widget deleted"
166
  msgstr ""
167
 
168
+ #: tmp/inc/admin.php:675
169
  msgid "Widget added"
170
  msgstr ""
171
 
172
+ #: tmp/inc/admin.php:679
173
  msgid "Widget edited"
174
  msgstr ""
175
 
176
+ #: tmp/inc/admin.php:683
177
  msgid "Widget duplicated"
178
  msgstr ""
179
 
180
+ #: tmp/inc/admin.php:687
181
  msgid "Widget moved"
182
  msgstr ""
183
 
184
+ #: tmp/inc/admin.php:695
185
  msgid "Row deleted"
186
  msgstr ""
187
 
188
+ #: tmp/inc/admin.php:699
189
  msgid "Row added"
190
  msgstr ""
191
 
192
+ #: tmp/inc/admin.php:703
193
  msgid "Row edited"
194
  msgstr ""
195
 
196
+ #: tmp/inc/admin.php:707
197
  msgid "Row moved"
198
  msgstr ""
199
 
200
+ #: tmp/inc/admin.php:711
201
  msgid "Row duplicated"
202
  msgstr ""
203
 
204
+ #: tmp/inc/admin.php:715
205
  msgid "Row pasted"
206
  msgstr ""
207
 
208
+ #: tmp/inc/admin.php:721
209
  msgid "Cell resized"
210
  msgstr ""
211
 
212
+ #: tmp/inc/admin.php:727
213
  msgid "Prebuilt layout loaded"
214
  msgstr ""
215
 
216
+ #: tmp/inc/admin.php:735
217
  msgid "Loading prebuilt layout"
218
  msgstr ""
219
 
220
+ #: tmp/inc/admin.php:737
221
  msgid "Would you like to copy this editor's existing content to Page Builder?"
222
  msgstr ""
223
 
224
+ #: tmp/inc/admin.php:739
225
  msgid "Would you like to clear your Page Builder content and revert to using the standard visual editor?"
226
  msgstr ""
227
 
228
+ #: tmp/inc/admin.php:743
229
  msgid "Layout Builder Widget"
230
  msgstr ""
231
 
232
+ #: tmp/inc/admin.php:747, tmp/tpl/js-templates.php:207, tmp/tpl/js-templates.php:849
233
  msgid "Are you sure?"
234
  msgstr ""
235
 
236
+ #: tmp/inc/admin.php:751
237
  msgid "%s is ready to insert."
238
  msgstr ""
239
 
240
+ #: tmp/inc/admin.php:759
241
  msgid "Add Widget Below"
242
  msgstr ""
243
 
244
+ #: tmp/inc/admin.php:761
245
  msgid "Add Widget to Cell"
246
  msgstr ""
247
 
248
+ #: tmp/inc/admin.php:763, tmp/tpl/js-templates.php:453
249
  msgid "Search Widgets"
250
  msgstr ""
251
 
252
+ #: tmp/inc/admin.php:767, tmp/tpl/js-templates.php:33, tmp/tpl/js-templates.php:37
253
  msgid "Add Row"
254
  msgstr ""
255
 
256
+ #: tmp/inc/admin.php:769
257
  msgid "Column"
258
  msgstr ""
259
 
260
+ #: tmp/inc/admin.php:773
261
  msgid "Cell Actions"
262
  msgstr ""
263
 
264
+ #: tmp/inc/admin.php:775
265
  msgid "Paste Widget"
266
  msgstr ""
267
 
268
+ #: tmp/inc/admin.php:779
269
  msgid "Widget Actions"
270
  msgstr ""
271
 
272
+ #: tmp/inc/admin.php:781
273
  msgid "Edit Widget"
274
  msgstr ""
275
 
276
+ #: tmp/inc/admin.php:783
277
  msgid "Duplicate Widget"
278
  msgstr ""
279
 
280
+ #: tmp/inc/admin.php:785
281
  msgid "Delete Widget"
282
  msgstr ""
283
 
284
+ #: tmp/inc/admin.php:787
285
  msgid "Copy Widget"
286
  msgstr ""
287
 
288
+ #: tmp/inc/admin.php:789
289
  msgid "Paste Widget Below"
290
  msgstr ""
291
 
292
+ #: tmp/inc/admin.php:793
293
  msgid "Row Actions"
294
  msgstr ""
295
 
296
+ #: tmp/inc/admin.php:795, tmp/tpl/js-templates.php:203
297
  msgid "Edit Row"
298
  msgstr ""
299
 
300
+ #: tmp/inc/admin.php:797, tmp/tpl/js-templates.php:205
301
  msgid "Duplicate Row"
302
  msgstr ""
303
 
304
+ #: tmp/inc/admin.php:799, tmp/tpl/js-templates.php:207
305
  msgid "Delete Row"
306
  msgstr ""
307
 
308
+ #: tmp/inc/admin.php:801
309
  msgid "Copy Row"
310
  msgstr ""
311
 
312
+ #: tmp/inc/admin.php:803
313
  msgid "Paste Row"
314
  msgstr ""
315
 
316
+ #: tmp/inc/admin.php:807
317
  msgid "Draft"
318
  msgstr ""
319
 
320
+ #: tmp/inc/admin.php:809
321
  msgid "Untitled"
322
  msgstr ""
323
 
324
+ #: tmp/inc/admin.php:813
325
  msgid "New Row"
326
  msgstr ""
327
 
328
+ #: tmp/inc/admin.php:815, tmp/inc/admin.php:831, tmp/inc/styles.php:183, tmp/tpl/js-templates.php:137
329
  msgid "Row"
330
  msgstr ""
331
 
332
+ #: tmp/inc/admin.php:821
333
  msgid "Hmmm... Adding layout elements is not enabled. Please check if Page Builder has been configured to allow adding elements."
334
  msgstr ""
335
 
336
+ #: tmp/inc/admin.php:823
337
  msgid "Add a {{%= items[0] %}} to get started."
338
  msgstr ""
339
 
340
+ #: tmp/inc/admin.php:825
341
  msgid "Add a {{%= items[0] %}} or {{%= items[1] %}} to get started."
342
  msgstr ""
343
 
344
+ #: tmp/inc/admin.php:827
345
  msgid "Add a {{%= items[0] %}}, {{%= items[1] %}} or {{%= items[2] %}} to get started."
346
  msgstr ""
347
 
348
+ #: tmp/inc/admin.php:829, tmp/inc/styles.php:316, tmp/tpl/js-templates.php:135
349
  msgid "Widget"
350
  msgstr ""
351
 
352
+ #: tmp/inc/admin.php:833, tmp/tpl/js-templates.php:139
353
  msgid "Prebuilt Layout"
354
  msgstr ""
355
 
356
+ #: tmp/inc/admin.php:837
357
  msgid "Read our %s if you need help."
358
  msgstr ""
359
 
360
+ #: tmp/inc/admin.php:839, tmp/tpl/js-templates.php:141
361
  msgid "documentation"
362
  msgstr ""
363
 
364
+ #: tmp/inc/admin.php:857
365
  msgid "Page Builder layouts"
366
  msgstr ""
367
 
368
+ #: tmp/inc/admin.php:859
369
  msgid "Error uploading or importing file."
370
  msgstr ""
371
 
372
+ #: tmp/inc/admin.php:1175, tmp/inc/home.php:26
373
  msgid "Home Page"
374
  msgstr ""
375
 
376
+ #: tmp/inc/admin.php:1363
377
  msgid "Untitled Widget"
378
  msgstr ""
379
 
380
+ #: tmp/inc/admin.php:1693
381
  msgid "You need to install 1{%1$s} to use the widget 2{%2$s}."
382
  msgstr ""
383
 
384
+ #: tmp/inc/admin.php:1705
385
  msgid "Save and reload this page to start using the widget after you've installed it."
386
  msgstr ""
387
 
388
+ #: tmp/inc/admin.php:1737
389
  msgid "The widget 1{%1$s} is not available. Please try locate and install the missing plugin. Post on the 2{support forums} if you need help."
390
  msgstr ""
391
 
392
+ #: tmp/inc/admin.php:2069
393
  msgid "%s Widgets"
394
  msgstr ""
395
 
396
+ #: tmp/inc/admin.php:2161
397
  msgid "12 Page Builder Tips"
398
  msgstr ""
399
 
400
+ #: tmp/inc/admin.php:2167
401
  msgid "Sign up to our newsletter and we'll send you this free Page Builder video course."
402
  msgstr ""
403
 
404
+ #: tmp/inc/admin.php:2169
405
  msgid "12 tips that'll help you get the most out of Page Builder."
406
  msgstr ""
407
 
408
+ #: tmp/inc/admin.php:2171
409
  msgid "Watch the video to find out more, then sign up below to get started."
410
  msgstr ""
411
 
412
+ #: tmp/inc/admin.php:2173, tmp/inc/admin.php:2193
413
  msgid "We'll email you a confirmation. You can unsubscribe at any time."
414
  msgstr ""
415
 
416
+ #: tmp/inc/admin.php:2181
417
  msgid "Free Page Builder Addons"
418
  msgstr ""
419
 
420
+ #: tmp/inc/admin.php:2187
421
  msgid "The free animations addon allows you to add beautiful animations to Page Builder elements."
422
  msgstr ""
423
 
424
+ #: tmp/inc/admin.php:2189
425
  msgid "Sign up to our newsletter and we'll send you the addon as a free gift."
426
  msgstr ""
427
 
428
+ #: tmp/inc/admin.php:2191
429
  msgid "Plus, we'll send you even more powerful addons, for as long as you're subscribed."
430
  msgstr ""
431
 
432
+ #: tmp/inc/admin.php:2223
433
  msgid "Watch Intro Video"
434
  msgstr ""
435
 
436
+ #: tmp/inc/admin.php:2225
437
  msgid "Loaded from Vimeo Servers"
438
  msgstr ""
439
 
440
+ #: tmp/inc/admin.php:2227
441
  msgid "Please enter a valid email address."
442
  msgstr ""
443
 
444
+ #: tmp/inc/admin.php:2231
445
  msgid "Your Name"
446
  msgstr ""
447
 
448
+ #: tmp/inc/admin.php:2233
449
  msgid "Your Email"
450
  msgstr ""
451
 
452
+ #: tmp/inc/admin.php:2235
453
  msgid "Sign Up"
454
  msgstr ""
455
 
456
+ #: tmp/inc/admin.php:2237, tmp/tpl/js-templates.php:477
457
  msgid "Close"
458
  msgstr ""
459
 
460
+ #: tmp/inc/admin.php:2259
461
  msgid "Get a lightbox addon for SiteOrigin widgets"
462
  msgstr ""
463
 
464
+ #: tmp/inc/admin.php:2267
465
  msgid "Get the row, cell and widget animations addon"
466
  msgstr ""
467
 
468
+ #: tmp/inc/admin.php:2275
469
  msgid "Get premium email support for SiteOrigin Page Builder"
470
  msgstr ""
471
 
525
  msgid "Page Builder Content"
526
  msgstr ""
527
 
528
+ #: tmp/inc/settings.php:389, tmp/settings/tpl/settings.php:9
529
  msgid "SiteOrigin Page Builder"
530
  msgstr ""
531
 
532
+ #: tmp/inc/settings.php:443
533
  msgid "Page Builder Settings"
534
  msgstr ""
535
 
536
+ #: tmp/inc/settings.php:475
537
  msgid "General"
538
  msgstr ""
539
 
540
+ #: tmp/inc/settings.php:487
541
  msgid "Post Types"
542
  msgstr ""
543
 
544
+ #: tmp/inc/settings.php:491
545
  msgid "The post types to use Page Builder on."
546
  msgstr ""
547
 
548
+ #: tmp/inc/settings.php:501
549
  msgid "Live Editor Quick Link"
550
  msgstr ""
551
 
552
+ #: tmp/inc/settings.php:503
553
  msgid "Display a Live Editor button in the admin bar."
554
  msgstr ""
555
 
556
+ #: tmp/inc/settings.php:513
557
  msgid "Display Widget Count"
558
  msgstr ""
559
 
560
+ #: tmp/inc/settings.php:515
561
  msgid "Display a widget count in the admin lists of posts/pages where you're using Page Builder."
562
  msgstr ""
563
 
564
+ #: tmp/inc/settings.php:525
565
  msgid "Limit Parallax Motion"
566
  msgstr ""
567
 
568
+ #: tmp/inc/settings.php:527
569
  msgid "How many pixels of scrolling result in a single pixel of parallax motion. 0 means automatic. Lower values give more noticeable effect."
570
  msgstr ""
571
 
572
+ #: tmp/inc/settings.php:537
573
  msgid "Sidebars Emulator"
574
  msgstr ""
575
 
576
+ #: tmp/inc/settings.php:539
577
  msgid "Page Builder will create an emulated sidebar, that contains all widgets in the page."
578
  msgstr ""
579
 
580
+ #: tmp/inc/settings.php:549
581
  msgid "Upgrade Teaser"
582
  msgstr ""
583
 
584
+ #: tmp/inc/settings.php:553
585
  msgid "Display the %sSiteOrigin Premium%s upgrade teaser in the Page Builder toolbar."
586
  msgstr ""
587
 
588
+ #: tmp/inc/settings.php:569
589
  msgid "Page Builder Learning"
590
  msgstr ""
591
 
592
+ #: tmp/inc/settings.php:571
593
  msgid "Display buttons for Page Builder learning."
594
  msgstr ""
595
 
596
+ #: tmp/inc/settings.php:581
597
  msgid "Default To Page Builder Interface"
598
  msgstr ""
599
 
600
+ #: tmp/inc/settings.php:583
601
  msgid "New posts/pages that you create will start with the Page Builder loaded."
602
  msgstr ""
603
 
604
+ #: tmp/inc/settings.php:595
605
  msgid "Widgets"
606
  msgstr ""
607
 
608
+ #: tmp/inc/settings.php:607
609
  msgid "Widget Title HTML"
610
  msgstr ""
611
 
612
+ #: tmp/inc/settings.php:609
613
  msgid "The HTML used for widget titles. {{title}} is replaced with the widget title."
614
  msgstr ""
615
 
616
+ #: tmp/inc/settings.php:619
617
  msgid "Add Widget Class"
618
  msgstr ""
619
 
620
+ #: tmp/inc/settings.php:621
621
  msgid "Add the widget class to Page Builder widgets. Disable this if you're experiencing conflicts."
622
  msgstr ""
623
 
624
+ #: tmp/inc/settings.php:631
625
  msgid "Legacy Bundled Widgets"
626
  msgstr ""
627
 
628
+ #: tmp/inc/settings.php:633
629
  msgid "Load legacy widgets from Page Builder 1."
630
  msgstr ""
631
 
632
+ #: tmp/inc/settings.php:645
633
  msgid "Display recommend widgets in Page Builder add widget dialog."
634
  msgstr ""
635
 
636
+ #: tmp/inc/settings.php:657, tmp/inc/styles-admin.php:78
637
  msgid "Layout"
638
  msgstr ""
639
 
640
+ #: tmp/inc/settings.php:673
641
  msgid "Responsive Layout"
642
  msgstr ""
643
 
644
+ #: tmp/inc/settings.php:675
645
  msgid "Collapse widgets, rows and columns on mobile devices."
646
  msgstr ""
647
 
648
+ #: tmp/inc/settings.php:685
649
  msgid "Use Tablet Layout"
650
  msgstr ""
651
 
652
+ #: tmp/inc/settings.php:687
653
  msgid "Collapses columns differently on tablet devices."
654
  msgstr ""
655
 
656
+ #: tmp/inc/settings.php:699
657
  msgid "Detect older browsers"
658
  msgstr ""
659
 
660
+ #: tmp/inc/settings.php:701
661
  msgid "Never"
662
  msgstr ""
663
 
664
+ #: tmp/inc/settings.php:703
665
  msgid "Always"
666
  msgstr ""
667
 
668
+ #: tmp/inc/settings.php:707
669
  msgid "Use Legacy Layout Engine"
670
  msgstr ""
671
 
672
+ #: tmp/inc/settings.php:709
673
  msgid "The CSS and HTML uses floats instead of flexbox for compatibility with very old browsers."
674
  msgstr ""
675
 
676
+ #: tmp/inc/settings.php:721
677
  msgid "Tablet Width"
678
  msgstr ""
679
 
680
+ #: tmp/inc/settings.php:723
681
  msgid "Device width, in pixels, to collapse into a tablet view ."
682
  msgstr ""
683
 
684
+ #: tmp/inc/settings.php:735
685
  msgid "Mobile Width"
686
  msgstr ""
687
 
688
+ #: tmp/inc/settings.php:737
689
  msgid "Device width, in pixels, to collapse into a mobile view ."
690
  msgstr ""
691
 
692
+ #: tmp/inc/settings.php:749
693
  msgid "Row/Widget Bottom Margin"
694
  msgstr ""
695
 
696
+ #: tmp/inc/settings.php:751
697
  msgid "Default margin below rows and widgets."
698
  msgstr ""
699
 
700
+ #: tmp/inc/settings.php:761
701
  msgid "Last Row With Margin"
702
  msgstr ""
703
 
704
+ #: tmp/inc/settings.php:763
705
  msgid "Allow margin in last row."
706
  msgstr ""
707
 
708
+ #: tmp/inc/settings.php:775
709
  msgid "Row Gutter"
710
  msgstr ""
711
 
712
+ #: tmp/inc/settings.php:777
713
  msgid "Default spacing between columns in each row."
714
  msgstr ""
715
 
716
+ #: tmp/inc/settings.php:789
717
  msgid "Full Width Container"
718
  msgstr ""
719
 
720
+ #: tmp/inc/settings.php:791
721
  msgid "The container used for the full width layout."
722
  msgstr ""
723
 
724
+ #: tmp/inc/settings.php:805
725
  msgid "Content"
726
  msgstr ""
727
 
728
+ #: tmp/inc/settings.php:817
729
  msgid "Copy Content"
730
  msgstr ""
731
 
732
+ #: tmp/inc/settings.php:819
733
  msgid "Copy content from Page Builder to post content."
734
  msgstr ""
735
 
736
+ #: tmp/inc/settings.php:829
737
  msgid "Copy Styles"
738
  msgstr ""
739
 
740
+ #: tmp/inc/settings.php:831
741
  msgid "Include styles into your Post Content. This keeps page layouts, even when Page Builder is deactivated."
742
  msgstr ""
743
 
744
+ #: tmp/inc/settings.php:925, tmp/inc/styles-admin.php:248
745
  msgid "Enabled"
746
  msgstr ""
747
 
1173
  msgid "Save Settings"
1174
  msgstr ""
1175
 
1176
+ #: tmp/siteorigin-panels.php:611
1177
  msgid "Read More"
1178
  msgstr ""
1179
 
1180
+ #: tmp/siteorigin-panels.php:731
1181
  msgid "Edit Home Page"
1182
  msgstr ""
1183
 
1184
+ #: tmp/siteorigin-panels.php:771, tmp/tpl/js-templates.php:67, tmp/tpl/js-templates.php:71
1185
  msgid "Live Editor"
1186
  msgstr ""
1187
 
1221
  msgid "Read the 1{full documentation} on SiteOrigin. Ask a question on our 2{support forum} if you need help and sign up to 3{our newsletter} to stay up to date with future developments."
1222
  msgstr ""
1223
 
1224
+ #: tmp/tpl/js-templates.php:23, tmp/tpl/js-templates.php:27
1225
  msgid "Add Widget"
1226
  msgstr ""
1227
 
1228
+ #: tmp/tpl/js-templates.php:43, tmp/tpl/js-templates.php:779
1229
  msgid "Prebuilt Layouts"
1230
  msgstr ""
1231
 
1232
+ #: tmp/tpl/js-templates.php:47
1233
  msgid "Layouts"
1234
  msgstr ""
1235
 
1236
+ #: tmp/tpl/js-templates.php:57
1237
  msgid "Edit History"
1238
  msgstr ""
1239
 
1240
+ #: tmp/tpl/js-templates.php:61
1241
  msgid "History"
1242
  msgstr ""
1243
 
1244
+ #: tmp/tpl/js-templates.php:83
1245
  msgid "Page Builder Addons"
1246
  msgstr ""
1247
 
1248
+ #: tmp/tpl/js-templates.php:97
1249
  msgid "Learn Page Builder"
1250
  msgstr ""
1251
 
1252
+ #: tmp/tpl/js-templates.php:101
1253
  msgid "Learn"
1254
  msgstr ""
1255
 
1256
+ #: tmp/tpl/js-templates.php:109
1257
  msgid "Revert to Editor"
1258
  msgstr ""
1259
 
1260
+ #: tmp/tpl/js-templates.php:133
1261
  msgid "Add a %s, %s or %s to get started. Read our %s if you need help."
1262
  msgstr ""
1263
 
1264
+ #: tmp/tpl/js-templates.php:155
1265
  msgid "Pro Tip"
1266
  msgstr ""
1267
 
1268
+ #: tmp/tpl/js-templates.php:295
1269
  msgid "Edit"
1270
  msgstr ""
1271
 
1272
+ #: tmp/tpl/js-templates.php:297, tmp/tpl/js-templates.php:541, tmp/tpl/js-templates.php:711
1273
  msgid "Duplicate"
1274
  msgstr ""
1275
 
1276
+ #: tmp/tpl/js-templates.php:299, tmp/tpl/js-templates.php:539, tmp/tpl/js-templates.php:709
1277
  msgid "Delete"
1278
  msgstr ""
1279
 
1280
+ #: tmp/tpl/js-templates.php:417, tmp/tpl/js-templates.php:547, tmp/tpl/js-templates.php:725, tmp/tpl/js-templates.php:1113
1281
  msgid "Done"
1282
  msgstr ""
1283
 
1284
+ #: tmp/tpl/js-templates.php:445
1285
  msgid "Add New Widget %s"
1286
  msgstr ""
1287
 
1288
+ #: tmp/tpl/js-templates.php:647
1289
  msgid "Left to Right"
1290
  msgstr ""
1291
 
1292
+ #: tmp/tpl/js-templates.php:649
1293
  msgid "Right to Left"
1294
  msgstr ""
1295
 
1296
+ #: tmp/tpl/js-templates.php:671
1297
  msgid "1{Set row layout}: %1$s columns with a ratio of %2$s going from %3$s"
1298
  msgstr ""
1299
 
1300
+ #: tmp/tpl/js-templates.php:683
1301
  msgid "Set"
1302
  msgstr ""
1303
 
1304
+ #: tmp/tpl/js-templates.php:721, tmp/tpl/js-templates.php:837
1305
  msgid "Insert"
1306
  msgstr ""
1307
 
1308
+ #: tmp/tpl/js-templates.php:761
1309
  msgid "Page Builder Layouts"
1310
  msgstr ""
1311
 
1312
+ #: tmp/tpl/js-templates.php:769
1313
  msgid "Search"
1314
  msgstr ""
1315
 
1316
+ #: tmp/tpl/js-templates.php:799
1317
  msgid "Import/Export"
1318
  msgstr ""
1319
 
1320
+ #: tmp/tpl/js-templates.php:813
1321
  msgid "Clone: %s"
1322
  msgstr ""
1323
 
1324
+ #: tmp/tpl/js-templates.php:845
1325
  msgid "Insert after"
1326
  msgstr ""
1327
 
1328
+ #: tmp/tpl/js-templates.php:847
1329
  msgid "Insert before"
1330
  msgstr ""
1331
 
1332
+ #: tmp/tpl/js-templates.php:849
1333
  msgid "Replace current"
1334
  msgstr ""
1335
 
1336
+ #: tmp/tpl/js-templates.php:871
1337
  msgid "Do you want to browse the Prebuilt Layouts directory?"
1338
  msgstr ""
1339
 
1340
+ #: tmp/tpl/js-templates.php:873
1341
  msgid "Enable"
1342
  msgstr ""
1343
 
1344
+ #: tmp/tpl/js-templates.php:899
1345
  msgid "Your search didn't return any results"
1346
  msgstr ""
1347
 
1348
+ #: tmp/tpl/js-templates.php:955
1349
  msgid "Previous"
1350
  msgstr ""
1351
 
1352
+ #: tmp/tpl/js-templates.php:957
1353
  msgid "Next"
1354
  msgstr ""
1355
 
1356
+ #: tmp/tpl/js-templates.php:977
1357
  msgid "Drop import file here"
1358
  msgstr ""
1359
 
1360
+ #: tmp/tpl/js-templates.php:979
1361
  msgid "Or"
1362
  msgstr ""
1363
 
1364
+ #: tmp/tpl/js-templates.php:985
1365
  msgid "Select Import File"
1366
  msgstr ""
1367
 
1368
+ #: tmp/tpl/js-templates.php:1013
1369
  msgid "Download Layout"
1370
  msgstr ""
1371
 
1372
+ #: tmp/tpl/js-templates.php:1035
1373
  msgid "Page Builder Change History"
1374
  msgstr ""
1375
 
1376
+ #: tmp/tpl/js-templates.php:1065
1377
  msgid "Restore Version"
1378
  msgstr ""
1379
 
1380
+ #: tmp/tpl/js-templates.php:1101, tmp/tpl/js-templates.php:1103
1381
  msgid "Collapse"
1382
  msgstr ""
1383
 
1384
+ #: tmp/tpl/js-templates.php:1101
1385
  msgid "Expand"
1386
  msgstr ""
1387
 
1388
+ #: tmp/tpl/js-templates.php:1117
1389
  msgid "Toggle desktop mode"
1390
  msgstr ""
1391
 
1392
+ #: tmp/tpl/js-templates.php:1123
1393
  msgid "Toggle tablet mode"
1394
  msgstr ""
1395
 
1396
+ #: tmp/tpl/js-templates.php:1129
1397
  msgid "Toggle mobile mode"
1398
  msgstr ""
1399
 
1400
+ #: tmp/tpl/js-templates.php:1207
1401
  msgid "No Results"
1402
  msgstr ""
1403
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 4.9
5
- Stable tag: 2.6.2
6
- Build time: 2018-01-23T10:38:09+02:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/contribution/
@@ -96,6 +96,12 @@ We've tried to ensure that Page Builder is compatible with most plugin widgets.
96
 
97
  == Changelog ==
98
 
 
 
 
 
 
 
99
  = 2.6.2 - 23 January 2018 =
100
  * Prevent Gutenberg from taking over existing PB pages.
101
  * Remove PB metaboxes from Gutenberg editor.
2
  Tags: page builder, responsive, widget, widgets, builder, page, admin, gallery, content, cms, pages, post, css, layout, grid
3
  Requires at least: 4.4
4
  Tested up to: 4.9
5
+ Stable tag: 2.6.3
6
+ Build time: 2018-03-06T11:33:07+02:00
7
  License: GPLv3
8
  License URI: http://www.gnu.org/licenses/gpl.html
9
  Donate link: https://siteorigin.com/downloads/contribution/
96
 
97
  == Changelog ==
98
 
99
+ = 2.6.3 - 6 March 2018 =
100
+ * Use `delete_post_meta_by_key` instead of direct DB query to clear old cache renders.
101
+ * Removed special handling for retrieving data from TinyMCE editor fields. Just use the field value directly.
102
+ * Show correct preview for current editor when another editor has created an autosave.
103
+ * Use minified CSS files.
104
+
105
  = 2.6.2 - 23 January 2018 =
106
  * Prevent Gutenberg from taking over existing PB pages.
107
  * Remove PB metaboxes from Gutenberg editor.
siteorigin-panels.php CHANGED
@@ -1,527 +1,528 @@
1
- <?php
2
- /*
3
- Plugin Name: Page Builder by SiteOrigin
4
- Plugin URI: https://siteorigin.com/page-builder/
5
- Description: A drag and drop, responsive page builder that simplifies building your website.
6
- Version: 2.6.2
7
- Author: SiteOrigin
8
- Author URI: https://siteorigin.com
9
- License: GPL3
10
- License URI: http://www.gnu.org/licenses/gpl.html
11
- Donate link: http://siteorigin.com/page-builder/#donate
12
- */
13
-
14
- define( 'SITEORIGIN_PANELS_VERSION', '2.6.2' );
15
- if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
- define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
- }
18
- define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-262' );
19
-
20
- require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
21
-
22
- class SiteOrigin_Panels {
23
-
24
- function __construct() {
25
- register_activation_hook( __FILE__, array( 'SiteOrigin_Panels', 'activate' ) );
26
-
27
- // Register the autoloader
28
- spl_autoload_register( array( $this, 'autoloader' ) );
29
-
30
- add_action( 'plugins_loaded', array( $this, 'version_check' ) );
31
- add_action( 'plugins_loaded', array( $this, 'init' ) );
32
- add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 );
33
-
34
- add_action('widgets_init', array( $this, 'widgets_init' ) );
35
-
36
- add_filter( 'body_class', array( $this, 'body_class' ) );
37
- add_filter( 'siteorigin_panels_data', array( $this, 'process_panels_data' ), 5 );
38
- add_filter( 'siteorigin_panels_widget_class', array( $this, 'fix_namespace_escaping' ), 5 );
39
-
40
- if ( is_admin() ) {
41
- // Setup all the admin classes
42
- SiteOrigin_Panels_Settings::single();
43
- SiteOrigin_Panels_Revisions::single();
44
- SiteOrigin_Panels_Admin::single();
45
-
46
- if( ! class_exists( 'SiteOrigin_Learn_Dialog' ) ) {
47
- include plugin_dir_path( __FILE__ ) . 'learn/learn.php';
48
- }
49
- }
50
-
51
- // Include the live editor file if we're in live editor mode.
52
- if ( self::is_live_editor() ) {
53
- SiteOrigin_Panels_Live_Editor::single();
54
- }
55
-
56
- SiteOrigin_Panels::renderer();
57
- SiteOrigin_Panels_Styles_Admin::single();
58
-
59
- if( siteorigin_panels_setting( 'bundled-widgets' ) && ! function_exists( 'origin_widgets_init' ) ) {
60
- require_once plugin_dir_path( __FILE__ ) . 'widgets/widgets.php';
61
- }
62
-
63
- SiteOrigin_Panels_Widget_Shortcode::init();
64
-
65
- // We need to generate fresh post content
66
- add_filter( 'the_content', array( $this, 'generate_post_content' ) );
67
- add_filter( 'wp_enqueue_scripts', array( $this, 'generate_post_css' ) );
68
-
69
- // Content cache has been removed. SiteOrigin_Panels_Cache_Renderer just deletes any existing caches.
70
- SiteOrigin_Panels_Cache_Renderer::single();
71
-
72
-
73
- define( 'SITEORIGIN_PANELS_BASE_FILE', __FILE__ );
74
- }
75
-
76
-
77
- public static function single() {
78
- static $single;
79
- return empty( $single ) ? $single = new self() : $single;
80
- }
81
-
82
- /**
83
- * Get an instance of the renderer
84
- *
85
- * @return SiteOrigin_Panels_Renderer
86
- */
87
- public static function renderer(){
88
- static $renderer;
89
- if( empty( $renderer ) ) {
90
- switch( siteorigin_panels_setting( 'legacy-layout' ) ) {
91
- case 'always':
92
- $renderer = SiteOrigin_Panels_Renderer_Legacy::single();
93
- break;
94
-
95
- case 'never':
96
- $renderer = SiteOrigin_Panels_Renderer::single();
97
- break;
98
-
99
- default :
100
- $renderer = self::is_legacy_browser() ?
101
- SiteOrigin_Panels_Renderer_Legacy::single() :
102
- SiteOrigin_Panels_Renderer::single();
103
- break;
104
- }
105
- }
106
-
107
- return $renderer;
108
- }
109
-
110
- public static function is_legacy_browser(){
111
- $agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
112
- if( empty( $agent ) ) return false;
113
-
114
- return
115
- // IE lte 10
116
- ( preg_match('/MSIE\s(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 10 ) ||
117
- // Chrome lte 25
118
- ( preg_match('/Chrome\/(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 25 ) ||
119
- // Firefox lte 21
120
- ( preg_match('/Firefox\/(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 21 ) ||
121
- // Safari lte 7
122
- ( preg_match('/Version\/(?P<v>\d+).*?Safari\/\d+/i', $agent, $B) && $B['v'] <= 6 );
123
- }
124
-
125
- /**
126
- * Autoload Page Builder specific classses.
127
- *
128
- * @param $class
129
- */
130
- public static function autoloader( $class ) {
131
- $filename = false;
132
- if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 ) {
133
- $filename = str_replace( 'SiteOrigin_Panels_Widgets_', '', $class );
134
- $filename = str_replace( '_', '-', $filename );
135
- $filename = strtolower( preg_replace( '/([a-z])([A-Z])/', '$1-$2', $filename ) );
136
- $filename = plugin_dir_path( __FILE__ ) . 'inc/widgets/' . $filename . '.php';
137
- }
138
- else if ( strpos( $class, 'SiteOrigin_Panels_' ) === 0 ) {
139
- $filename = str_replace( array( 'SiteOrigin_Panels_', '_' ), array( '', '-' ), $class );
140
- $filename = plugin_dir_path( __FILE__ ) . 'inc/' . strtolower( $filename ) . '.php';
141
- }
142
-
143
- if ( ! empty( $filename ) && file_exists( $filename ) ) {
144
- include $filename;
145
- }
146
- }
147
-
148
- public static function activate() {
149
- add_option( 'siteorigin_panels_initial_version', SITEORIGIN_PANELS_VERSION, '', 'no' );
150
- }
151
-
152
- /**
153
- * Initialize SiteOrigin Page Builder
154
- *
155
- * @action plugins_loaded
156
- */
157
- public function init() {
158
- if (
159
- ! is_admin() &&
160
- siteorigin_panels_setting( 'sidebars-emulator' ) &&
161
- ( ! get_option( 'permalink_structure' ) || get_option( 'rewrite_rules' ) )
162
- ) {
163
- // Initialize the sidebars emulator
164
- SiteOrigin_Panels_Sidebars_Emulator::single();
165
- }
166
-
167
- // Initialize the language
168
- load_plugin_textdomain( 'siteorigin-panels', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
169
-
170
- // Initialize all the extra classes
171
- SiteOrigin_Panels_Home::single();
172
-
173
- // Check if we need to initialize the admin class.
174
- if ( is_admin() ) {
175
- SiteOrigin_Panels_Admin::single();
176
- }
177
- }
178
-
179
- /**
180
- * @return mixed|void Are we currently viewing the home page
181
- */
182
- public static function is_home() {
183
- $home = ( is_front_page() && is_page() && get_option( 'show_on_front' ) == 'page' && get_option( 'page_on_front' ) == get_the_ID() && get_post_meta( get_the_ID(), 'panels_data' ) );
184
-
185
- return apply_filters( 'siteorigin_panels_is_home', $home );
186
- }
187
-
188
- /**
189
- * Check if we're currently viewing a page builder page.
190
- *
191
- * @param bool $can_edit Also check if the user can edit this page
192
- *
193
- * @return bool
194
- */
195
- public static function is_panel( $can_edit = false ) {
196
- // Check if this is a panel
197
- $is_panel = ( siteorigin_panels_is_home() || ( is_singular() && get_post_meta( get_the_ID(), 'panels_data', false ) ) );
198
-
199
- return $is_panel && ( ! $can_edit || ( ( is_singular() && current_user_can( 'edit_post', get_the_ID() ) ) || ( siteorigin_panels_is_home() && current_user_can( 'edit_theme_options' ) ) ) );
200
- }
201
-
202
- /**
203
- * Check if we're in the Live Editor in the frontend.
204
- *
205
- * @return bool
206
- */
207
- static function is_live_editor(){
208
- return ! empty( $_GET['siteorigin_panels_live_editor'] );
209
- }
210
-
211
- public static function preview_url() {
212
- global $post, $wp_post_types;
213
-
214
- if (
215
- empty( $post ) ||
216
- empty( $wp_post_types ) ||
217
- empty( $wp_post_types[ $post->post_type ] ) ||
218
- ! $wp_post_types[ $post->post_type ]->public
219
- ) {
220
- $preview_url = add_query_arg(
221
- 'siteorigin_panels_live_editor',
222
- 'true',
223
- admin_url( 'admin-ajax.php?action=so_panels_live_editor_preview' )
224
- );
225
- $preview_url = wp_nonce_url( $preview_url, 'live-editor-preview', '_panelsnonce' );
226
- } else {
227
- $preview_url = add_query_arg( 'siteorigin_panels_live_editor', 'true', set_url_scheme( get_permalink() ) );
228
- }
229
-
230
- return $preview_url;
231
- }
232
-
233
- /**
234
- * Get the Page Builder data for the home page.
235
- *
236
- * @return bool|mixed
237
- */
238
- public function get_home_page_data() {
239
- $page_id = get_option( 'page_on_front' );
240
- if ( empty( $page_id ) ) {
241
- $page_id = get_option( 'siteorigin_panels_home_page_id' );
242
- }
243
- if ( empty( $page_id ) ) {
244
- return false;
245
- }
246
-
247
- $panels_data = get_post_meta( $page_id, 'panels_data', true );
248
- if ( is_null( $panels_data ) ) {
249
- // Load the default layout
250
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
251
- $panels_data = ! empty( $layouts['default_home'] ) ? $layouts['default_home'] : current( $layouts );
252
- }
253
-
254
- return $panels_data;
255
- }
256
-
257
- /**
258
- * Generate post content for the current post.
259
- *
260
- * @param $content
261
- *
262
- * @return string
263
- *
264
- * @filter the_content
265
- */
266
- public function generate_post_content( $content ) {
267
- global $post, $preview;
268
- if ( empty( $post ) && ! in_the_loop() ) {
269
- return $content;
270
- }
271
-
272
- if ( ! apply_filters( 'siteorigin_panels_filter_content_enabled', true ) ) {
273
- return $content;
274
- }
275
-
276
- $post_id = get_the_ID();
277
- // If we're viewing a preview make sure we load and render the autosave post's meta.
278
- if ( $preview ) {
279
- $preview_post = wp_get_post_autosave( $post_id );
280
- if ( ! empty( $preview_post ) ) {
281
- $post_id = $preview_post->ID;
282
- }
283
- }
284
- // Check if this post has panels_data
285
- if ( get_post_meta( $post_id, 'panels_data', true ) ) {
286
- $panel_content = SiteOrigin_Panels::renderer()->render(
287
- $post_id,
288
- // Add CSS if this is not the main single post, this is handled by add_single_css
289
- $preview || $post_id !== get_queried_object_id()
290
- );
291
-
292
- if ( ! empty( $panel_content ) ) {
293
- $content = $panel_content;
294
-
295
- if ( ! is_singular() ) {
296
- // This is an archive page, so try strip out anything after the more text
297
-
298
- if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
299
- $content = explode( $matches[0], $content, 2 );
300
- $content = $content[0];
301
- $content = force_balance_tags( $content );
302
- if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) ) {
303
- $more_link_text = strip_tags( wp_kses_no_null( trim( $matches[1] ) ) );
304
- } else {
305
- $more_link_text = __( 'Read More', 'siteorigin-panels' );
306
- }
307
-
308
- $more_link = apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-{$post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
309
- $content .= '<p>' . $more_link . '</p>';
310
- }
311
- }
312
- }
313
- }
314
-
315
- return $content;
316
- }
317
-
318
- /**
319
- * Generate CSS for the current post
320
- */
321
- public function generate_post_css() {
322
- if( is_singular() && get_post_meta( get_the_ID(), 'panels_data', true ) ) {
323
- $renderer = SiteOrigin_Panels::renderer();
324
- $renderer->add_inline_css( get_the_ID(), $renderer->generate_css( get_the_ID() ) );
325
- }
326
- }
327
-
328
- /**
329
- * Add all the necessary body classes.
330
- *
331
- * @param $classes
332
- *
333
- * @return array
334
- */
335
- function body_class( $classes ) {
336
- if( self::is_panel() ) {
337
- $classes[] = 'siteorigin-panels';
338
- $classes[] = 'siteorigin-panels-before-js';
339
-
340
- add_action( 'wp_footer', array( $this, 'strip_before_js' ), 99 );
341
- }
342
- if( self::is_home() ) $classes[] = 'siteorigin-panels-home';
343
- if( self::is_live_editor() ) $classes[] = 'siteorigin-panels-live-editor';
344
-
345
- return $classes;
346
- }
347
-
348
- /**
349
- * Add the Edit Home Page item to the admin bar.
350
- *
351
- * @param WP_Admin_Bar $admin_bar
352
- *
353
- * @return WP_Admin_Bar
354
- */
355
- function admin_bar_menu( $admin_bar ) {
356
- // Add the edit home page link
357
- if (
358
- siteorigin_panels_setting( 'home-page' ) &&
359
- current_user_can( 'edit_theme_options' ) &&
360
- ( is_home() || is_front_page() )
361
- ) {
362
- if ( ( is_page() && get_post_meta( get_the_ID(), 'panels_data', true ) !== '' ) || ! is_page() ) {
363
- $admin_bar->add_node( array(
364
- 'id' => 'edit-home-page',
365
- 'title' => __( 'Edit Home Page', 'siteorigin-panels' ),
366
- 'href' => admin_url( 'themes.php?page=so_panels_home_page' )
367
- ) );
368
-
369
- if ( is_page() ) {
370
- // Remove the standard edit button
371
- $admin_bar->remove_node( 'edit' );
372
- }
373
- }
374
- }
375
-
376
- // Add a Live Edit link if this is a Page Builder page that the user can edit
377
- if (
378
- siteorigin_panels_setting( 'live-editor-quick-link' ) &&
379
- is_singular() &&
380
- current_user_can( 'edit_post', get_the_ID() ) &&
381
- get_post_meta( get_the_ID(), 'panels_data', true )
382
- ) {
383
- $admin_bar->add_node( array(
384
- 'id' => 'so_live_editor',
385
- 'title' => __( 'Live Editor', 'siteorigin-panels' ),
386
- 'href' => add_query_arg( 'so_live_editor', 1, get_edit_post_link( get_the_ID() ) ),
387
- 'meta' => array(
388
- 'class' => 'live-edit-page'
389
- )
390
- ) );
391
-
392
- add_action( 'wp_enqueue_scripts', array( $this, 'live_edit_link_style' ) );
393
- }
394
-
395
- return $admin_bar;
396
- }
397
-
398
- function widgets_init(){
399
- register_widget( 'SiteOrigin_Panels_Widgets_PostContent' );
400
- register_widget( 'SiteOrigin_Panels_Widgets_PostLoop' );
401
- register_widget( 'SiteOrigin_Panels_Widgets_Layout' );
402
- }
403
-
404
- function live_edit_link_style() {
405
- if ( is_singular() && current_user_can( 'edit_post', get_the_ID() ) && get_post_meta( get_the_ID(), 'panels_data', true ) ) {
406
- // Add the style for the eye icon before the Live Editor link
407
- $css = '#wpadminbar #wp-admin-bar-so_live_editor > .ab-item:before {
408
- content: "\f177";
409
- top: 2px;
410
- }';
411
- wp_add_inline_style( 'siteorigin-panels-front', $css );
412
- }
413
- }
414
-
415
- /**
416
- * Process panels data to make sure everything is properly formatted
417
- *
418
- * @param array $panels_data
419
- *
420
- * @return array
421
- */
422
- function process_panels_data( $panels_data ) {
423
-
424
- // Process all widgets to make sure that panels_info is properly represented
425
- if ( ! empty( $panels_data['widgets'] ) && is_array( $panels_data['widgets'] ) ) {
426
-
427
- $last_gi = 0;
428
- $last_ci = 0;
429
- $last_wi = 0;
430
-
431
- foreach ( $panels_data['widgets'] as &$widget ) {
432
- // Transfer legacy content
433
- if ( empty( $widget['panels_info'] ) && ! empty( $widget['info'] ) ) {
434
- $widget['panels_info'] = $widget['info'];
435
- unset( $widget['info'] );
436
- }
437
-
438
- // Filter the widgets to add indexes
439
- if ( $widget['panels_info']['grid'] != $last_gi ) {
440
- $last_gi = $widget['panels_info']['grid'];
441
- $last_ci = $widget['panels_info']['cell'];
442
- $last_wi = 0;
443
- } elseif ( $widget['panels_info']['cell'] != $last_ci ) {
444
- $last_ci = $widget['panels_info']['cell'];
445
- $last_wi = 0;
446
- }
447
- $widget['panels_info']['cell_index'] = $last_wi ++;
448
- }
449
-
450
- foreach ( $panels_data['grids'] as &$grid ) {
451
- if ( ! empty( $grid['style'] ) && is_string( $grid['style'] ) ) {
452
- $grid['style'] = array();
453
- }
454
- }
455
- }
456
-
457
- return $panels_data;
458
- }
459
-
460
- /**
461
- * Fix class names that have been incorrectly escaped
462
- *
463
- * @param $class
464
- *
465
- * @return mixed
466
- */
467
- public function fix_namespace_escaping( $class ){
468
- return preg_replace( '/\\\\+/', '\\', $class );
469
- }
470
-
471
- public static function front_css_url(){
472
- return self::renderer()->front_css_url();
473
- }
474
-
475
- /**
476
- * Trigger a siteorigin_panels_version_changed action if the version has changed
477
- */
478
- public function version_check(){
479
- $active_version = get_option( 'siteorigin_panels_active_version', false );
480
- if( empty( $active_version ) || $active_version !== SITEORIGIN_PANELS_VERSION ) {
481
- do_action( 'siteorigin_panels_version_changed' );
482
- update_option( 'siteorigin_panels_active_version', SITEORIGIN_PANELS_VERSION );
483
- }
484
- }
485
-
486
- static function display_learn_button() {
487
- return siteorigin_panels_setting( 'display-learn' ) &&
488
- apply_filters( 'siteorigin_panels_learn', true );
489
- }
490
-
491
- /**
492
- * Script that removes the siteorigin-panels-before-js class from the body.
493
- */
494
- public function strip_before_js(){
495
- ?><script type="text/javascript">document.body.className = document.body.className.replace("siteorigin-panels-before-js","");</script><?php
496
- }
497
-
498
- /**
499
- * Should we display premium addon messages
500
- *
501
- * @return bool
502
- */
503
- public static function display_premium_teaser(){
504
- return siteorigin_panels_setting( 'display-teaser' ) &&
505
- apply_filters( 'siteorigin_premium_upgrade_teaser', true ) &&
506
- ! defined( 'SITEORIGIN_PREMIUM_VERSION' );
507
- }
508
-
509
- /**
510
- * Get the premium upgrade URL
511
- *
512
- * @return string
513
- */
514
- public static function premium_url( $featured_addon = false ) {
515
- $ref = apply_filters( 'siteorigin_premium_affiliate_id', '' );
516
- $url = 'https://siteorigin.com/downloads/premium/?featured_plugin=siteorigin-panels';
517
- if( ! empty( $featured_addon ) ) {
518
- $url = add_query_arg( 'featured_addon', urlencode( $featured_addon ), $url );
519
- }
520
- if( ! empty( $ref ) ) {
521
- $url = add_query_arg( 'ref', urlencode( $ref ), $url );
522
- }
523
- return $url;
524
- }
525
- }
526
-
527
- SiteOrigin_Panels::single();
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Page Builder by SiteOrigin
4
+ Plugin URI: https://siteorigin.com/page-builder/
5
+ Description: A drag and drop, responsive page builder that simplifies building your website.
6
+ Version: 2.6.3
7
+ Author: SiteOrigin
8
+ Author URI: https://siteorigin.com
9
+ License: GPL3
10
+ License URI: http://www.gnu.org/licenses/gpl.html
11
+ Donate link: http://siteorigin.com/page-builder/#donate
12
+ */
13
+
14
+ define( 'SITEORIGIN_PANELS_VERSION', '2.6.3' );
15
+ if ( ! defined( 'SITEORIGIN_PANELS_JS_SUFFIX' ) ) {
16
+ define( 'SITEORIGIN_PANELS_JS_SUFFIX', '.min' );
17
+ }
18
+ define( 'SITEORIGIN_PANELS_CSS_SUFFIX', '.min' );
19
+ define( 'SITEORIGIN_PANELS_VERSION_SUFFIX', '-263' );
20
+
21
+ require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22
+
23
+ class SiteOrigin_Panels {
24
+
25
+ function __construct() {
26
+ register_activation_hook( __FILE__, array( 'SiteOrigin_Panels', 'activate' ) );
27
+
28
+ // Register the autoloader
29
+ spl_autoload_register( array( $this, 'autoloader' ) );
30
+
31
+ add_action( 'plugins_loaded', array( $this, 'version_check' ) );
32
+ add_action( 'plugins_loaded', array( $this, 'init' ) );
33
+ add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 );
34
+
35
+ add_action('widgets_init', array( $this, 'widgets_init' ) );
36
+
37
+ add_filter( 'body_class', array( $this, 'body_class' ) );
38
+ add_filter( 'siteorigin_panels_data', array( $this, 'process_panels_data' ), 5 );
39
+ add_filter( 'siteorigin_panels_widget_class', array( $this, 'fix_namespace_escaping' ), 5 );
40
+
41
+ if ( is_admin() ) {
42
+ // Setup all the admin classes
43
+ SiteOrigin_Panels_Settings::single();
44
+ SiteOrigin_Panels_Revisions::single();
45
+ SiteOrigin_Panels_Admin::single();
46
+
47
+ if( ! class_exists( 'SiteOrigin_Learn_Dialog' ) ) {
48
+ include plugin_dir_path( __FILE__ ) . 'learn/learn.php';
49
+ }
50
+ }
51
+
52
+ // Include the live editor file if we're in live editor mode.
53
+ if ( self::is_live_editor() ) {
54
+ SiteOrigin_Panels_Live_Editor::single();
55
+ }
56
+
57
+ SiteOrigin_Panels::renderer();
58
+ SiteOrigin_Panels_Styles_Admin::single();
59
+
60
+ if( siteorigin_panels_setting( 'bundled-widgets' ) && ! function_exists( 'origin_widgets_init' ) ) {
61
+ require_once plugin_dir_path( __FILE__ ) . 'widgets/widgets.php';
62
+ }
63
+
64
+ SiteOrigin_Panels_Widget_Shortcode::init();
65
+
66
+ // We need to generate fresh post content
67
+ add_filter( 'the_content', array( $this, 'generate_post_content' ) );
68
+ add_filter( 'wp_enqueue_scripts', array( $this, 'generate_post_css' ) );
69
+
70
+ // Content cache has been removed. SiteOrigin_Panels_Cache_Renderer just deletes any existing caches.
71
+ SiteOrigin_Panels_Cache_Renderer::single();
72
+
73
+
74
+ define( 'SITEORIGIN_PANELS_BASE_FILE', __FILE__ );
75
+ }
76
+
77
+
78
+ public static function single() {
79
+ static $single;
80
+ return empty( $single ) ? $single = new self() : $single;
81
+ }
82
+
83
+ /**
84
+ * Get an instance of the renderer
85
+ *
86
+ * @return SiteOrigin_Panels_Renderer
87
+ */
88
+ public static function renderer(){
89
+ static $renderer;
90
+ if( empty( $renderer ) ) {
91
+ switch( siteorigin_panels_setting( 'legacy-layout' ) ) {
92
+ case 'always':
93
+ $renderer = SiteOrigin_Panels_Renderer_Legacy::single();
94
+ break;
95
+
96
+ case 'never':
97
+ $renderer = SiteOrigin_Panels_Renderer::single();
98
+ break;
99
+
100
+ default :
101
+ $renderer = self::is_legacy_browser() ?
102
+ SiteOrigin_Panels_Renderer_Legacy::single() :
103
+ SiteOrigin_Panels_Renderer::single();
104
+ break;
105
+ }
106
+ }
107
+
108
+ return $renderer;
109
+ }
110
+
111
+ public static function is_legacy_browser(){
112
+ $agent = ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
113
+ if( empty( $agent ) ) return false;
114
+
115
+ return
116
+ // IE lte 10
117
+ ( preg_match('/MSIE\s(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 10 ) ||
118
+ // Chrome lte 25
119
+ ( preg_match('/Chrome\/(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 25 ) ||
120
+ // Firefox lte 21
121
+ ( preg_match('/Firefox\/(?P<v>\d+)/i', $agent, $B) && $B['v'] <= 21 ) ||
122
+ // Safari lte 7
123
+ ( preg_match('/Version\/(?P<v>\d+).*?Safari\/\d+/i', $agent, $B) && $B['v'] <= 6 );
124
+ }
125
+
126
+ /**
127
+ * Autoload Page Builder specific classses.
128
+ *
129
+ * @param $class
130
+ */
131
+ public static function autoloader( $class ) {
132
+ $filename = false;
133
+ if ( strpos( $class, 'SiteOrigin_Panels_Widgets_' ) === 0 ) {
134
+ $filename = str_replace( 'SiteOrigin_Panels_Widgets_', '', $class );
135
+ $filename = str_replace( '_', '-', $filename );
136
+ $filename = strtolower( preg_replace( '/([a-z])([A-Z])/', '$1-$2', $filename ) );
137
+ $filename = plugin_dir_path( __FILE__ ) . 'inc/widgets/' . $filename . '.php';
138
+ }
139
+ else if ( strpos( $class, 'SiteOrigin_Panels_' ) === 0 ) {
140
+ $filename = str_replace( array( 'SiteOrigin_Panels_', '_' ), array( '', '-' ), $class );
141
+ $filename = plugin_dir_path( __FILE__ ) . 'inc/' . strtolower( $filename ) . '.php';
142
+ }
143
+
144
+ if ( ! empty( $filename ) && file_exists( $filename ) ) {
145
+ include $filename;
146
+ }
147
+ }
148
+
149
+ public static function activate() {
150
+ add_option( 'siteorigin_panels_initial_version', SITEORIGIN_PANELS_VERSION, '', 'no' );
151
+ }
152
+
153
+ /**
154
+ * Initialize SiteOrigin Page Builder
155
+ *
156
+ * @action plugins_loaded
157
+ */
158
+ public function init() {
159
+ if (
160
+ ! is_admin() &&
161
+ siteorigin_panels_setting( 'sidebars-emulator' ) &&
162
+ ( ! get_option( 'permalink_structure' ) || get_option( 'rewrite_rules' ) )
163
+ ) {
164
+ // Initialize the sidebars emulator
165
+ SiteOrigin_Panels_Sidebars_Emulator::single();
166
+ }
167
+
168
+ // Initialize the language
169
+ load_plugin_textdomain( 'siteorigin-panels', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
170
+
171
+ // Initialize all the extra classes
172
+ SiteOrigin_Panels_Home::single();
173
+
174
+ // Check if we need to initialize the admin class.
175
+ if ( is_admin() ) {
176
+ SiteOrigin_Panels_Admin::single();
177
+ }
178
+ }
179
+
180
+ /**
181
+ * @return mixed|void Are we currently viewing the home page
182
+ */
183
+ public static function is_home() {
184
+ $home = ( is_front_page() && is_page() && get_option( 'show_on_front' ) == 'page' && get_option( 'page_on_front' ) == get_the_ID() && get_post_meta( get_the_ID(), 'panels_data' ) );
185
+
186
+ return apply_filters( 'siteorigin_panels_is_home', $home );
187
+ }
188
+
189
+ /**
190
+ * Check if we're currently viewing a page builder page.
191
+ *
192
+ * @param bool $can_edit Also check if the user can edit this page
193
+ *
194
+ * @return bool
195
+ */
196
+ public static function is_panel( $can_edit = false ) {
197
+ // Check if this is a panel
198
+ $is_panel = ( siteorigin_panels_is_home() || ( is_singular() && get_post_meta( get_the_ID(), 'panels_data', false ) ) );
199
+
200
+ return $is_panel && ( ! $can_edit || ( ( is_singular() && current_user_can( 'edit_post', get_the_ID() ) ) || ( siteorigin_panels_is_home() && current_user_can( 'edit_theme_options' ) ) ) );
201
+ }
202
+
203
+ /**
204
+ * Check if we're in the Live Editor in the frontend.
205
+ *
206
+ * @return bool
207
+ */
208
+ static function is_live_editor(){
209
+ return ! empty( $_GET['siteorigin_panels_live_editor'] );
210
+ }
211
+
212
+ public static function preview_url() {
213
+ global $post, $wp_post_types;
214
+
215
+ if (
216
+ empty( $post ) ||
217
+ empty( $wp_post_types ) ||
218
+ empty( $wp_post_types[ $post->post_type ] ) ||
219
+ ! $wp_post_types[ $post->post_type ]->public
220
+ ) {
221
+ $preview_url = add_query_arg(
222
+ 'siteorigin_panels_live_editor',
223
+ 'true',
224
+ admin_url( 'admin-ajax.php?action=so_panels_live_editor_preview' )
225
+ );
226
+ $preview_url = wp_nonce_url( $preview_url, 'live-editor-preview', '_panelsnonce' );
227
+ } else {
228
+ $preview_url = add_query_arg( 'siteorigin_panels_live_editor', 'true', set_url_scheme( get_permalink() ) );
229
+ }
230
+
231
+ return $preview_url;
232
+ }
233
+
234
+ /**
235
+ * Get the Page Builder data for the home page.
236
+ *
237
+ * @return bool|mixed
238
+ */
239
+ public function get_home_page_data() {
240
+ $page_id = get_option( 'page_on_front' );
241
+ if ( empty( $page_id ) ) {
242
+ $page_id = get_option( 'siteorigin_panels_home_page_id' );
243
+ }
244
+ if ( empty( $page_id ) ) {
245
+ return false;
246
+ }
247
+
248
+ $panels_data = get_post_meta( $page_id, 'panels_data', true );
249
+ if ( is_null( $panels_data ) ) {
250
+ // Load the default layout
251
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
252
+ $panels_data = ! empty( $layouts['default_home'] ) ? $layouts['default_home'] : current( $layouts );
253
+ }
254
+
255
+ return $panels_data;
256
+ }
257
+
258
+ /**
259
+ * Generate post content for the current post.
260
+ *
261
+ * @param $content
262
+ *
263
+ * @return string
264
+ *
265
+ * @filter the_content
266
+ */
267
+ public function generate_post_content( $content ) {
268
+ global $post, $preview;
269
+ if ( empty( $post ) && ! in_the_loop() ) {
270
+ return $content;
271
+ }
272
+
273
+ if ( ! apply_filters( 'siteorigin_panels_filter_content_enabled', true ) ) {
274
+ return $content;
275
+ }
276
+
277
+ $post_id = get_the_ID();
278
+ // If we're viewing a preview make sure we load and render the autosave post's meta.
279
+ if ( $preview ) {
280
+ $preview_post = wp_get_post_autosave( $post_id, get_current_user_id() );
281
+ if ( ! empty( $preview_post ) ) {
282
+ $post_id = $preview_post->ID;
283
+ }
284
+ }
285
+ // Check if this post has panels_data
286
+ if ( get_post_meta( $post_id, 'panels_data', true ) ) {
287
+ $panel_content = SiteOrigin_Panels::renderer()->render(
288
+ $post_id,
289
+ // Add CSS if this is not the main single post, this is handled by add_single_css
290
+ $preview || $post_id !== get_queried_object_id()
291
+ );
292
+
293
+ if ( ! empty( $panel_content ) ) {
294
+ $content = $panel_content;
295
+
296
+ if ( ! is_singular() ) {
297
+ // This is an archive page, so try strip out anything after the more text
298
+
299
+ if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
300
+ $content = explode( $matches[0], $content, 2 );
301
+ $content = $content[0];
302
+ $content = force_balance_tags( $content );
303
+ if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) ) {
304
+ $more_link_text = strip_tags( wp_kses_no_null( trim( $matches[1] ) ) );
305
+ } else {
306
+ $more_link_text = __( 'Read More', 'siteorigin-panels' );
307
+ }
308
+
309
+ $more_link = apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-{$post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
310
+ $content .= '<p>' . $more_link . '</p>';
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ return $content;
317
+ }
318
+
319
+ /**
320
+ * Generate CSS for the current post
321
+ */
322
+ public function generate_post_css() {
323
+ if( is_singular() && get_post_meta( get_the_ID(), 'panels_data', true ) ) {
324
+ $renderer = SiteOrigin_Panels::renderer();
325
+ $renderer->add_inline_css( get_the_ID(), $renderer->generate_css( get_the_ID() ) );
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Add all the necessary body classes.
331
+ *
332
+ * @param $classes
333
+ *
334
+ * @return array
335
+ */
336
+ function body_class( $classes ) {
337
+ if( self::is_panel() ) {
338
+ $classes[] = 'siteorigin-panels';
339
+ $classes[] = 'siteorigin-panels-before-js';
340
+
341
+ add_action( 'wp_footer', array( $this, 'strip_before_js' ), 99 );
342
+ }
343
+ if( self::is_home() ) $classes[] = 'siteorigin-panels-home';
344
+ if( self::is_live_editor() ) $classes[] = 'siteorigin-panels-live-editor';
345
+
346
+ return $classes;
347
+ }
348
+
349
+ /**
350
+ * Add the Edit Home Page item to the admin bar.
351
+ *
352
+ * @param WP_Admin_Bar $admin_bar
353
+ *
354
+ * @return WP_Admin_Bar
355
+ */
356
+ function admin_bar_menu( $admin_bar ) {
357
+ // Add the edit home page link
358
+ if (
359
+ siteorigin_panels_setting( 'home-page' ) &&
360
+ current_user_can( 'edit_theme_options' ) &&
361
+ ( is_home() || is_front_page() )
362
+ ) {
363
+ if ( ( is_page() && get_post_meta( get_the_ID(), 'panels_data', true ) !== '' ) || ! is_page() ) {
364
+ $admin_bar->add_node( array(
365
+ 'id' => 'edit-home-page',
366
+ 'title' => __( 'Edit Home Page', 'siteorigin-panels' ),
367
+ 'href' => admin_url( 'themes.php?page=so_panels_home_page' )
368
+ ) );
369
+
370
+ if ( is_page() ) {
371
+ // Remove the standard edit button
372
+ $admin_bar->remove_node( 'edit' );
373
+ }
374
+ }
375
+ }
376
+
377
+ // Add a Live Edit link if this is a Page Builder page that the user can edit
378
+ if (
379
+ siteorigin_panels_setting( 'live-editor-quick-link' ) &&
380
+ is_singular() &&
381
+ current_user_can( 'edit_post', get_the_ID() ) &&
382
+ get_post_meta( get_the_ID(), 'panels_data', true )
383
+ ) {
384
+ $admin_bar->add_node( array(
385
+ 'id' => 'so_live_editor',
386
+ 'title' => __( 'Live Editor', 'siteorigin-panels' ),
387
+ 'href' => add_query_arg( 'so_live_editor', 1, get_edit_post_link( get_the_ID() ) ),
388
+ 'meta' => array(
389
+ 'class' => 'live-edit-page'
390
+ )
391
+ ) );
392
+
393
+ add_action( 'wp_enqueue_scripts', array( $this, 'live_edit_link_style' ) );
394
+ }
395
+
396
+ return $admin_bar;
397
+ }
398
+
399
+ function widgets_init(){
400
+ register_widget( 'SiteOrigin_Panels_Widgets_PostContent' );
401
+ register_widget( 'SiteOrigin_Panels_Widgets_PostLoop' );
402
+ register_widget( 'SiteOrigin_Panels_Widgets_Layout' );
403
+ }
404
+
405
+ function live_edit_link_style() {
406
+ if ( is_singular() && current_user_can( 'edit_post', get_the_ID() ) && get_post_meta( get_the_ID(), 'panels_data', true ) ) {
407
+ // Add the style for the eye icon before the Live Editor link
408
+ $css = '#wpadminbar #wp-admin-bar-so_live_editor > .ab-item:before {
409
+ content: "\f177";
410
+ top: 2px;
411
+ }';
412
+ wp_add_inline_style( 'siteorigin-panels-front', $css );
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Process panels data to make sure everything is properly formatted
418
+ *
419
+ * @param array $panels_data
420
+ *
421
+ * @return array
422
+ */
423
+ function process_panels_data( $panels_data ) {
424
+
425
+ // Process all widgets to make sure that panels_info is properly represented
426
+ if ( ! empty( $panels_data['widgets'] ) && is_array( $panels_data['widgets'] ) ) {
427
+
428
+ $last_gi = 0;
429
+ $last_ci = 0;
430
+ $last_wi = 0;
431
+
432
+ foreach ( $panels_data['widgets'] as &$widget ) {
433
+ // Transfer legacy content
434
+ if ( empty( $widget['panels_info'] ) && ! empty( $widget['info'] ) ) {
435
+ $widget['panels_info'] = $widget['info'];
436
+ unset( $widget['info'] );
437
+ }
438
+
439
+ // Filter the widgets to add indexes
440
+ if ( $widget['panels_info']['grid'] != $last_gi ) {
441
+ $last_gi = $widget['panels_info']['grid'];
442
+ $last_ci = $widget['panels_info']['cell'];
443
+ $last_wi = 0;
444
+ } elseif ( $widget['panels_info']['cell'] != $last_ci ) {
445
+ $last_ci = $widget['panels_info']['cell'];
446
+ $last_wi = 0;
447
+ }
448
+ $widget['panels_info']['cell_index'] = $last_wi ++;
449
+ }
450
+
451
+ foreach ( $panels_data['grids'] as &$grid ) {
452
+ if ( ! empty( $grid['style'] ) && is_string( $grid['style'] ) ) {
453
+ $grid['style'] = array();
454
+ }
455
+ }
456
+ }
457
+
458
+ return $panels_data;
459
+ }
460
+
461
+ /**
462
+ * Fix class names that have been incorrectly escaped
463
+ *
464
+ * @param $class
465
+ *
466
+ * @return mixed
467
+ */
468
+ public function fix_namespace_escaping( $class ){
469
+ return preg_replace( '/\\\\+/', '\\', $class );
470
+ }
471
+
472
+ public static function front_css_url(){
473
+ return self::renderer()->front_css_url();
474
+ }
475
+
476
+ /**
477
+ * Trigger a siteorigin_panels_version_changed action if the version has changed
478
+ */
479
+ public function version_check(){
480
+ $active_version = get_option( 'siteorigin_panels_active_version', false );
481
+ if( empty( $active_version ) || $active_version !== SITEORIGIN_PANELS_VERSION ) {
482
+ do_action( 'siteorigin_panels_version_changed' );
483
+ update_option( 'siteorigin_panels_active_version', SITEORIGIN_PANELS_VERSION );
484
+ }
485
+ }
486
+
487
+ static function display_learn_button() {
488
+ return siteorigin_panels_setting( 'display-learn' ) &&
489
+ apply_filters( 'siteorigin_panels_learn', true );
490
+ }
491
+
492
+ /**
493
+ * Script that removes the siteorigin-panels-before-js class from the body.
494
+ */
495
+ public function strip_before_js(){
496
+ ?><script type="text/javascript">document.body.className = document.body.className.replace("siteorigin-panels-before-js","");</script><?php
497
+ }
498
+
499
+ /**
500
+ * Should we display premium addon messages
501
+ *
502
+ * @return bool
503
+ */
504
+ public static function display_premium_teaser(){
505
+ return siteorigin_panels_setting( 'display-teaser' ) &&
506
+ apply_filters( 'siteorigin_premium_upgrade_teaser', true ) &&
507
+ ! defined( 'SITEORIGIN_PREMIUM_VERSION' );
508
+ }
509
+
510
+ /**
511
+ * Get the premium upgrade URL
512
+ *
513
+ * @return string
514
+ */
515
+ public static function premium_url( $featured_addon = false ) {
516
+ $ref = apply_filters( 'siteorigin_premium_affiliate_id', '' );
517
+ $url = 'https://siteorigin.com/downloads/premium/?featured_plugin=siteorigin-panels';
518
+ if( ! empty( $featured_addon ) ) {
519
+ $url = add_query_arg( 'featured_addon', urlencode( $featured_addon ), $url );
520
+ }
521
+ if( ! empty( $ref ) ) {
522
+ $url = add_query_arg( 'ref', urlencode( $ref ), $url );
523
+ }
524
+ return $url;
525
+ }
526
+ }
527
+
528
+ SiteOrigin_Panels::single();
tpl/js-templates.php CHANGED
@@ -1,608 +1,608 @@
1
- <?php
2
- global $wp_widget_factory, $post;
3
- $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
4
- ?>
5
-
6
- <script type="text/template" id="siteorigin-panels-builder">
7
-
8
- <div class="siteorigin-panels-builder">
9
-
10
- <div class="so-builder-toolbar">
11
-
12
- <a class="so-tool-button so-widget-add" title="<?php esc_attr_e( 'Add Widget', 'siteorigin-panels' ) ?>">
13
- <span class="so-panels-icon so-panels-icon-add-widget"></span>
14
- <span class="so-button-text"><?php esc_html_e('Add Widget', 'siteorigin-panels') ?></span>
15
- </a>
16
-
17
- <a class="so-tool-button so-row-add" title="<?php esc_attr_e( 'Add Row', 'siteorigin-panels' ) ?>">
18
- <span class="so-panels-icon so-panels-icon-add-row"></span>
19
- <span class="so-button-text"><?php esc_html_e('Add Row', 'siteorigin-panels') ?></span>
20
- </a>
21
-
22
- <a class="so-tool-button so-prebuilt-add" title="<?php esc_attr_e( 'Prebuilt Layouts', 'siteorigin-panels' ) ?>">
23
- <span class="so-panels-icon so-panels-icon-layouts"></span>
24
- <span class="so-button-text"><?php esc_html_e('Layouts', 'siteorigin-panels') ?></span>
25
- </a>
26
-
27
- <?php if( !empty($post) ) : ?>
28
-
29
- <a class="so-tool-button so-history" style="display: none" title="<?php esc_attr_e( 'Edit History', 'siteorigin-panels' ) ?>">
30
- <span class="so-panels-icon so-panels-icon-history"></span>
31
- <span class="so-button-text"><?php _e('History', 'siteorigin-panels') ?></span>
32
- </a>
33
-
34
- <a class="so-tool-button so-live-editor" style="display: none" title="<?php esc_html_e( 'Live Editor', 'siteorigin-panels' ) ?>">
35
- <span class="so-panels-icon so-panels-icon-live-editor"></span>
36
- <span class="so-button-text"><?php _e('Live Editor', 'siteorigin-panels') ?></span>
37
- </a>
38
-
39
- <?php endif; ?>
40
-
41
- <?php if( SiteOrigin_Panels::display_premium_teaser() ) : ?>
42
- <a class="so-tool-button so-learn" title="<?php echo esc_attr_e( 'Page Builder Addons', 'siteorigin-panels' ) ?>" href="<?php echo esc_url( SiteOrigin_Panels::premium_url() ) ?>" style="margin-left: 10px;">
43
- <span class="so-panels-icon so-panels-icon-addons"></span>
44
- <span class="so-button-text"><?php echo esc_html_e( 'Addons', 'siteorigin-panels' ) ?></span>
45
- </a>
46
- <?php endif; ?>
47
-
48
- <?php if( SiteOrigin_Panels::display_learn_button() ) : ?>
49
- <a class="so-tool-button so-learn" title="<?php echo esc_attr_e( 'Learn Page Builder', 'siteorigin-panels' ) ?>" href="#siteorigin-learn-page-builder-tips" style="margin-left: 10px;">
50
- <span class="so-panels-icon so-panels-icon-learn"></span>
51
- <span class="so-button-text"><?php echo esc_html_e( 'Learn', 'siteorigin-panels' ) ?></span>
52
- </a>
53
- <?php endif ?>
54
-
55
- <a class="so-switch-to-standard"><?php _e('Revert to Editor', 'siteorigin-panels') ?></a>
56
-
57
- </div>
58
-
59
- <div class="so-rows-container">
60
-
61
- </div>
62
-
63
- <div class="so-panels-welcome-message">
64
- <div class="so-message-wrapper">
65
- <?php
66
- printf(
67
- __( 'Add a %s, %s or %s to get started. Read our %s if you need help.', 'siteorigin-panels' ),
68
- "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
69
- "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
70
- "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
71
- "<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
72
- );
73
- ?>
74
- </div>
75
-
76
- <?php if( SiteOrigin_Panels::display_premium_teaser() ) : ?>
77
- <div class="so-tip-wrapper">
78
- <strong><?php _e( 'Pro Tip', 'siteorigin-panels' ) ?>: </strong>
79
- <?php SiteOrigin_Panels_Admin::display_footer_premium_link() ?>
80
- </div>
81
- <?php endif; ?>
82
- </div>
83
-
84
- </div>
85
-
86
- </script>
87
-
88
- <script type="text/template" id="siteorigin-panels-builder-row">
89
- <div class="so-row-container ui-draggable so-row-color-{{%= rowColorLabel %}}">
90
-
91
- <div class="so-row-toolbar">
92
- {{% if( rowLabel ) { %}}
93
- <h3 class="so-row-label">{{%= rowLabel %}}</h3>
94
- {{% } %}}
95
- <span class="so-row-move so-tool-button"><span class="so-panels-icon so-panels-icon-move"></span></span>
96
-
97
- <span class="so-dropdown-wrapper">
98
- <a class="so-row-settings so-tool-button"><span class="so-panels-icon so-panels-icon-settings"></span></a>
99
-
100
- <div class="so-dropdown-links-wrapper">
101
- <ul>
102
- <li><a class="so-row-settings"><?php _e('Edit Row', 'siteorigin-panels') ?></a></li>
103
- <li><a class="so-row-duplicate"><?php _e('Duplicate Row', 'siteorigin-panels') ?></a></li>
104
- <li><a class="so-row-delete so-needs-confirm" data-confirm="<?php esc_attr_e('Are you sure?', 'siteorigin-panels') ?>"><?php _e('Delete Row', 'siteorigin-panels') ?></a></li>
105
- <li class="so-row-colors-container">
106
- <?php
107
- // See css/admin.less variable @row_colors. This should match the number of colors defined there.
108
- $row_color_count = 5;
109
-
110
- for ( $i = 1; $i <= $row_color_count; $i++ ) {
111
- $classes = array( 'so-row-color', 'so-row-color-' . $i );
112
-
113
- ?>
114
- <div data-color-label="<?php echo esc_attr( $i ); ?>"
115
- class="<?php echo esc_attr( implode( ' ', $classes ) ) ?>{{% if( rowColorLabel == '<?php echo esc_attr( $i ); ?>' ) print(' so-row-color-selected'); %}}"
116
- ></div>
117
- <?php
118
- }
119
- ?>
120
- </li>
121
- </ul>
122
- <div class="so-pointer"></div>
123
- </div>
124
- </span>
125
- </div>
126
-
127
- <div class="so-cells">
128
-
129
- </div>
130
-
131
- </div>
132
- </script>
133
-
134
- <script type="text/template" id="siteorigin-panels-builder-cell">
135
- <div class="cell">
136
- <div class="resize-handle"></div>
137
- <div class="cell-wrapper widgets-container">
138
- </div>
139
- </div>
140
- </script>
141
-
142
- <script type="text/template" id="siteorigin-panels-builder-widget">
143
- <div class="so-widget ui-draggable">
144
- <div class="so-widget-wrapper">
145
- <div class="title">
146
- <h4>{{%= title %}}</h4>
147
- <span class="actions">
148
- <a class="widget-edit"><?php _e('Edit', 'siteorigin-panels') ?></a>
149
- <a class="widget-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
150
- <a class="widget-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
151
- </span>
152
- </div>
153
- <small class="description">{{%= description %}}</small>
154
- </div>
155
- </div>
156
- </script>
157
-
158
- <script type="text/template" id="siteorigin-panels-dialog">
159
- <div class="so-panels-dialog {{% if(typeof left_sidebar != 'undefined') print('so-panels-dialog-has-left-sidebar '); if(typeof right_sidebar != 'undefined') print('so-panels-dialog-has-right-sidebar '); %}}">
160
-
161
- <div class="so-overlay"></div>
162
-
163
- <div class="so-title-bar {{% if ( dialogIcon ) print( 'so-has-icon' ) %}}">
164
- {{% if ( ! _.isEmpty( dialogIcon ) ) { %}}
165
- <div class="so-panels-icon so-panels-icon-{{%- dialogIcon %}}" />
166
- {{% } %}}
167
- <h3 class="so-title{{% if ( editableLabel ) print(' so-title-editable')%}}"
168
- {{% if ( editableLabel ) print('contenteditable="true" spellcheck="false" tabIndex="1"')%}}
169
- >{{%= title %}}</h3>
170
- <a class="so-previous so-nav"><span class="so-dialog-icon"></span></a>
171
- <a class="so-next so-nav"><span class="so-dialog-icon"></span></a>
172
- <a class="so-close"><span class="so-dialog-icon"></span></a>
173
- </div>
174
-
175
- <div class="so-toolbar">
176
- <div class="so-status">{{% if(typeof status != 'undefined') print(status); %}}</div>
177
- <div class="so-buttons">
178
- {{%= buttons %}}
179
- </div>
180
- </div>
181
-
182
- <div class="so-sidebar so-left-sidebar">
183
- {{% if(typeof left_sidebar != 'undefined') print(left_sidebar ); %}}
184
- </div>
185
-
186
- <div class="so-sidebar so-right-sidebar">
187
- {{% if(typeof right_sidebar != 'undefined') print(right_sidebar ); %}}
188
- </div>
189
-
190
- <div class="so-content panel-dialog">
191
- {{%= content %}}
192
- </div>
193
-
194
- </div>
195
- </script>
196
-
197
- <script type="text/template" id="siteorigin-panels-dialog-builder">
198
- <div class="dialog-data">
199
-
200
- <h3 class="title"><?php _e('Page Builder', 'siteorigin-panels') ?></h3>
201
-
202
- <div class="content">
203
- <div class="siteorigin-panels-builder">
204
-
205
- </div>
206
- </div>
207
-
208
- <div class="buttons">
209
- <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
210
- </div>
211
-
212
- </div>
213
- </script>
214
-
215
-
216
- <script type="text/template" id="siteorigin-panels-dialog-tab">
217
- <li><a href="{{% if(typeof tab != 'undefined') { print ( '#' + tab ); } %}}">{{%= title %}}</a></li>
218
- </script>
219
-
220
- <script type="text/template" id="siteorigin-panels-dialog-widgets">
221
- <div class="dialog-data">
222
-
223
- <h3 class="title"><?php printf( __('Add New Widget %s', 'siteorigin-panels'), '<span class="current-tab-title"></span>' ) ?></h3>
224
-
225
- <div class="left-sidebar">
226
-
227
- <input type="text" class="so-sidebar-search" placeholder="<?php esc_attr_e('Search Widgets', 'siteorigin-panels') ?>" />
228
-
229
- <ul class="so-sidebar-tabs">
230
- </ul>
231
-
232
- </div>
233
-
234
- <div class="content">
235
- <ul class="widget-type-list"></ul>
236
- </div>
237
-
238
- <div class="buttons">
239
- <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Close', 'siteorigin-panels') ?>" />
240
- </div>
241
-
242
- </div>
243
- </script>
244
-
245
- <script type="text/template" id="siteorigin-panels-dialog-widgets-widget">
246
- <li class="widget-type">
247
- <div class="widget-type-wrapper">
248
- <h3>{{%= title %}}</h3>
249
- <small class="description">{{%= description %}}</small>
250
- </div>
251
- </li>
252
- </script>
253
-
254
- <script type="text/template" id="siteorigin-panels-dialog-widget">
255
- <div class="dialog-data">
256
-
257
- <h3 class="title"><span class="widget-name"></span></h3>
258
-
259
- <div class="right-sidebar"></div>
260
-
261
- <div class="content">
262
-
263
- <div class="widget-form">
264
- </div>
265
-
266
- </div>
267
-
268
- <div class="buttons">
269
- <div class="action-buttons">
270
- <a class="so-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
271
- <a class="so-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
272
- </div>
273
-
274
- <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
275
- </div>
276
-
277
- </div>
278
- </script>
279
-
280
- <script type="text/template" id="siteorigin-panels-dialog-widget-sidebar-widget">
281
- <div class="so-widget">
282
- <h3>{{%= title %}}</h3>
283
- <small class="description">
284
- {{%= description %}}
285
- </small>
286
- </div>
287
- </script>
288
-
289
- <script type="text/template" id="siteorigin-panels-dialog-row">
290
- <div class="dialog-data">
291
-
292
- <h3 class="title">
293
- {{%= title %}}
294
- </h3>
295
-
296
- <div class="right-sidebar"></div>
297
-
298
- <div class="content">
299
-
300
- <div class="row-set-form">
301
- <?php
302
- $cells_field = apply_filters('siteorigin_panels_row_column_count_input', '<input type="number" min="1" max="12" name="cells" class="so-row-field" value="2" />');
303
- $ratios = apply_filters('siteorigin_panels_column_ratios', array(
304
- 'Even' => 1,
305
- 'Golden' => 0.61803398,
306
- 'Halves' => 0.5,
307
- 'Thirds' => 0.33333333,
308
- 'Diagon' => 0.41421356,
309
- 'Hecton' => 0.73205080,
310
- 'Hemidiagon' => 0.11803398,
311
- 'Penton' => 0.27201964,
312
- 'Trion' => 0.15470053,
313
- 'Quadriagon' => 0.207,
314
- 'Biauron' => 0.30901699,
315
- 'Bipenton' => 0.46,
316
- ) );
317
- $ratio_field = '<select name="ratio" class="so-row-field">';
318
- foreach( $ratios as $name => $value ) {
319
- $ratio_field .= '<option value="' . esc_attr($value) . '">' . esc_html($name . ' (' . round($value, 3) . ')') . '</option>';
320
- }
321
- $ratio_field .= '</select>';
322
-
323
- $direction_field = '<select name="ratio_direction" class="so-row-field">';
324
- $direction_field .= '<option value="right">' . esc_html__('Left to Right', 'siteorigin-panels') . '</option>';
325
- $direction_field .= '<option value="left">' . esc_html__('Right to Left', 'siteorigin-panels') . '</option>';
326
- $direction_field .= '</select>';
327
-
328
- printf(
329
- preg_replace(
330
- array(
331
- '/1\{ *(.*?) *\}/',
332
- ),
333
- array(
334
- '<strong>$1</strong>',
335
- ),
336
- __('1{Set row layout}: %1$s columns with a ratio of %2$s going from %3$s', 'siteorigin-panels')
337
- ),
338
- $cells_field,
339
- $ratio_field,
340
- $direction_field
341
- );
342
- echo '<button class="button-secondary set-row">' . esc_html__('Set', 'siteorigin-panels') . '</button>';
343
- ?>
344
- </div>
345
-
346
- <div class="row-preview">
347
-
348
- </div>
349
-
350
- </div>
351
-
352
- <div class="buttons">
353
- {{% if( dialogType == 'edit' ) { %}}
354
- <div class="action-buttons">
355
- <a class="so-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
356
- <a class="so-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
357
- </div>
358
- {{% } %}}
359
-
360
- {{% if( dialogType == 'create' ) { %}}
361
- <input type="button" class="button-primary so-insert" value="<?php esc_attr_e('Insert', 'siteorigin-panels') ?>" />
362
- {{% } else { %}}
363
- <input type="button" class="button-primary so-save" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
364
- {{% } %}}
365
- </div>
366
-
367
- </div>
368
- </script>
369
-
370
- <script type="text/template" id="siteorigin-panels-dialog-row-cell-preview">
371
- <div class="preview-cell" style="width: {{%- weight*100 %}}%">
372
- <div class="preview-cell-in">
373
- <div class="preview-cell-weight">{{% print(Math.round(weight * 1000) / 10) %}}</div>
374
- </div>
375
- </div>
376
- </script>
377
-
378
- <script type="text/template" id="siteorigin-panels-dialog-prebuilt">
379
- <div class="dialog-data">
380
-
381
- <h3 class="title"><?php _e('Page Builder Layouts', 'siteorigin-panels') ?></h3>
382
-
383
- <div class="left-sidebar">
384
-
385
- <input type="text" class="so-sidebar-search" placeholder="<?php esc_attr_e('Search', 'siteorigin-panels') ?>" />
386
-
387
- <ul class="so-sidebar-tabs">
388
- <?php if( !empty( $layouts ) ) : ?>
389
- <li>
390
- <a href="#prebuilt"><?php _e('Prebuilt Layouts', 'siteorigin-panels') ?></a>
391
- </li>
392
- <?php endif; ?>
393
-
394
- <?php
395
- $directories = SiteOrigin_Panels_Admin_Layouts::single()->get_directories();
396
- foreach ( $directories as $id => $directory ) {
397
- ?><li><a href="#directory-<?php echo urlencode( $id ) ?>"><?php echo esc_html( $directory['title'] ) ?></a></li><?php
398
- }
399
- ?>
400
- <li><a href="#import"><?php _e('Import/Export', 'siteorigin-panels') ?></a></li>
401
-
402
- <?php
403
- $post_types = siteorigin_panels_setting('post-types');
404
- foreach($post_types as $post_type) {
405
- $type = get_post_type_object( $post_type );
406
- if( empty($type) ) continue;
407
- ?><li><a href="#<?php echo 'clone_'.$post_type ?>"><?php printf( __('Clone: %s', 'siteorigin-panels'), $type->labels->name ) ?></a></li><?php
408
- }
409
- ?>
410
- </ul>
411
-
412
- </div>
413
-
414
- <div class="content">
415
- </div>
416
-
417
- <div class="buttons">
418
- <span class="so-dropdown-wrapper">
419
- <input type="button" class="button-primary so-dropdown-button so-import-layout disabled" value="<?php esc_attr_e('Insert', 'siteorigin-panels') ?>" disabled="disabled"/>
420
-
421
- <div class="so-dropdown-links-wrapper hidden">
422
- <ul class="so-layout-position">
423
- <li><a class="so-toolbar-button" data-value="after"><?php esc_html_e('Insert after', 'siteorigin-panels') ?></a></li>
424
- <li><a class="so-toolbar-button" data-value="before"><?php esc_html_e('Insert before', 'siteorigin-panels') ?></a></li>
425
- <li><a class="so-toolbar-button so-needs-confirm" data-value="replace" data-confirm="<?php esc_attr_e('Are you sure?', 'siteorigin-panels') ?>"><?php esc_html_e('Replace current', 'siteorigin-panels') ?></a></li>
426
- </ul>
427
- </div>
428
- </span>
429
- </div>
430
-
431
- </div>
432
- </script>
433
-
434
- <script type="text/template" id="siteorigin-panels-directory-enable">
435
- <div class="so-enable-prebuilt">
436
- <?php _e('Do you want to browse the Prebuilt Layouts directory?', 'siteorigin-panels') ?>
437
- <button class="button-primary so-panels-enable-directory"><?php _e('Enable', 'siteorigin-panels') ?></button>
438
- </div>
439
- </script>
440
-
441
- <script type="text/template" id="siteorigin-panels-directory-items">
442
- <div class="so-directory-items">
443
-
444
- <div class="so-directory-browse">
445
- </div>
446
-
447
- <div class="so-directory-items-wrapper">
448
- {{% if(items.length === 0) { %}}
449
- <div class="so-no-results">
450
- <?php _e( "Your search didn't return any results", 'siteorigin-panels' ); ?>
451
- </div>
452
- {{% } else { %}}
453
- {{% _.each(items, function(item) { %}}
454
- <div class="so-directory-item" data-layout-id="{{%- item.id %}}" data-layout-type="{{%- item.type %}}">
455
- <div class="so-directory-item-wrapper">
456
- <div class="so-screenshot" data-src="{{%- item.screenshot %}}">
457
- <div class="so-panels-loading so-screenshot-wrapper"></div>
458
- </div>
459
- <div class="so-description">{{%- item.description %}}</div>
460
-
461
- <div class="so-bottom">
462
- <h4 class="so-title">{{%= item.title %}}</h4>
463
- {{% if( item.preview ) { %}}
464
- <div class="so-buttons">
465
- <a href="{{%- item.preview %}}" class="button-secondary so-button-preview" target="_blank" rel="noopener noreferrer">Preview</a>
466
- </div>
467
- {{% } %}}
468
- </div>
469
- </div>
470
- </div>
471
- {{% }); %}}
472
- {{% } %}}
473
- </div>
474
-
475
- <div class="clear"></div>
476
-
477
- <div class="so-directory-pages">
478
- <a class="so-previous button-secondary" data-direction="prev"><?php _e('Previous', 'siteorigin-panels') ?></a>
479
- <a class="so-next button-secondary" data-direction="next"><?php _e('Next', 'siteorigin-panels') ?></a>
480
- </div>
481
- </div>
482
- </script>
483
-
484
- <script type="text/template" id="siteorigin-panels-dialog-prebuilt-importexport">
485
- <div class="import-export">
486
- <div class="import-upload-ui hide-if-no-js">
487
- <div class="drag-upload-area">
488
-
489
- <h2 class="drag-drop-message"><?php _e('Drop import file here', 'siteorigin-panels'); ?></h2>
490
- <p class="drag-drop-message"><?php _e('Or', 'siteorigin-panels') ?></p>
491
-
492
- <p class="drag-drop-buttons">
493
- <input type="button" value="<?php esc_attr_e('Select Import File', 'siteorigin-panels'); ?>" class="file-browse-button button" />
494
- </p>
495
-
496
- <p class="drag-drop-message js-so-selected-file"></p>
497
-
498
- <div class="progress-bar">
499
- <div class="progress-percent"></div>
500
- </div>
501
- </div>
502
- </div>
503
-
504
- <div class="export-file-ui">
505
- <iframe id="siteorigin-panels-export-iframe" style="display: none;" name="siteorigin-panels-export-iframe"></iframe>
506
- <form action="<?php echo admin_url('admin-ajax.php?action=so_panels_export_layout') ?>" target="siteorigin-panels-export-iframe" class="so-export" method="post">
507
- <input type="submit" value="<?php esc_attr_e('Download Layout', 'siteorigin-panels') ?>" class="button-primary" />
508
- <input type="hidden" name="panels_export_data" value="" />
509
- <?php wp_nonce_field('panels_action', '_panelsnonce') ?>
510
- </form>
511
- </div>
512
- </div>
513
- </script>
514
-
515
- <script type="text/template" id="siteorigin-panels-dialog-history">
516
- <div class="dialog-data">
517
-
518
- <h3 class="title"><?php _e('Page Builder Change History', 'siteorigin-panels') ?></h3>
519
-
520
- <div class="left-sidebar">
521
- <div class="history-entries"></div>
522
- </div>
523
-
524
- <div class="content">
525
- <form method="post" action="<?php echo SiteOrigin_Panels::preview_url() ?>" target="siteorigin-panels-history-iframe-{{%= cid %}}" class="history-form">
526
- <input type="hidden" name="live_editor_panels_data" value="">
527
- <input type="hidden" name="live_editor_post_ID" value="">
528
- </form>
529
- <iframe class="siteorigin-panels-history-iframe" name="siteorigin-panels-history-iframe-{{%= cid %}}" src=""></iframe>
530
- </div>
531
-
532
- <div class="buttons">
533
- <input type="button" class="button-primary so-restore" value="<?php esc_attr_e('Restore Version', 'siteorigin-panels') ?>" />
534
- </div>
535
-
536
- </div>
537
- </script>
538
-
539
- <script type="text/template" id="siteorigin-panels-dialog-history-entry">
540
- <div class="history-entry">
541
- <h3>{{%= title %}}{{% if( count > 1 ) { %}} <span class="count">({{%= count %}})</span>{{% } %}}</h3>
542
- <div class="timesince"></div>
543
- </div>
544
- </script>
545
-
546
- <script type="text/template" id="siteorigin-panels-live-editor">
547
- <div class="so-panels-live-editor">
548
-
549
- <div class="live-editor-collapse">
550
- <div class="collapse-icon"></div>
551
- <span data-collapse="<?php esc_attr_e( 'Collapse', 'siteorigin-panels' ) ?>" data-expand="<?php esc_attr_e( 'Expand', 'siteorigin-panels' ) ?>">
552
- <?php _e( 'Collapse', 'siteorigin-panels' ) ?>
553
- </span>
554
- </div>
555
-
556
- <div class="so-sidebar-tools">
557
- <button class="live-editor-close button-primary"><?php esc_html_e('Done', 'siteorigin-panels') ?></button>
558
-
559
- <a class="live-editor-mode live-editor-desktop so-active" title="<?php esc_attr_e( 'Toggle desktop mode', 'siteorigin-panels' ) ?>" data-mode="desktop">
560
- <span class="dashicons dashicons-desktop"></span>
561
- </a>
562
- <a class="live-editor-mode live-editor-tablet" title="<?php esc_attr_e( 'Toggle tablet mode', 'siteorigin-panels' ) ?>" data-mode="tablet">
563
- <span class="dashicons dashicons-tablet"></span>
564
- </a>
565
- <a class="live-editor-mode live-editor-mobile" title="<?php esc_attr_e( 'Toggle mobile mode', 'siteorigin-panels' ) ?>" data-mode="mobile">
566
- <span class="dashicons dashicons-smartphone"></span>
567
- </a>
568
-
569
- </div>
570
-
571
- <div class="so-sidebar">
572
- <div class="so-live-editor-builder"></div>
573
- </div>
574
-
575
- <div class="so-preview"></div>
576
-
577
- <div class="so-preview-overlay">
578
- <div class="so-loading-container"><div class="so-loading-bar"></div></div>
579
- </div>
580
-
581
- </div>
582
- </script>
583
-
584
- <script type="text/template" id="siteorigin-panels-context-menu">
585
- <div class="so-panels-contextual-menu"></div>
586
- </script>
587
-
588
- <script type="text/template" id="siteorigin-panels-context-menu-section">
589
- <div class="so-section">
590
- <h5>{{%- settings.sectionTitle %}}</h5>
591
-
592
- {{% if( settings.search ) { %}}
593
- <div class="so-search-wrapper">
594
- <input type="text" placeholder="{{%- settings.searchPlaceholder %}}" />
595
- </div>
596
- {{% } %}}
597
- <ul class="so-items">
598
- {{% for( var k in items ) { %}}
599
- <li data-key="{{%- k %}}" class="so-item {{% if( !_.isUndefined( items[k].confirm ) && items[k].confirm ) { print( 'so-confirm' ); } %}}">{{%= items[k][settings.titleKey] %}}</li>
600
- {{% } %}}
601
- </ul>
602
- {{% if( settings.search ) { %}}
603
- <div class="so-no-results">
604
- <?php _e('No Results', 'siteorigin-panels') ?>
605
- </div>
606
- {{% } %}}
607
- </div>
608
- </script>
1
+ <?php
2
+ global $wp_widget_factory, $post;
3
+ $layouts = apply_filters( 'siteorigin_panels_prebuilt_layouts', array() );
4
+ ?>
5
+
6
+ <script type="text/template" id="siteorigin-panels-builder">
7
+
8
+ <div class="siteorigin-panels-builder">
9
+
10
+ <div class="so-builder-toolbar">
11
+
12
+ <a class="so-tool-button so-widget-add" title="<?php esc_attr_e( 'Add Widget', 'siteorigin-panels' ) ?>">
13
+ <span class="so-panels-icon so-panels-icon-add-widget"></span>
14
+ <span class="so-button-text"><?php esc_html_e('Add Widget', 'siteorigin-panels') ?></span>
15
+ </a>
16
+
17
+ <a class="so-tool-button so-row-add" title="<?php esc_attr_e( 'Add Row', 'siteorigin-panels' ) ?>">
18
+ <span class="so-panels-icon so-panels-icon-add-row"></span>
19
+ <span class="so-button-text"><?php esc_html_e('Add Row', 'siteorigin-panels') ?></span>
20
+ </a>
21
+
22
+ <a class="so-tool-button so-prebuilt-add" title="<?php esc_attr_e( 'Prebuilt Layouts', 'siteorigin-panels' ) ?>">
23
+ <span class="so-panels-icon so-panels-icon-layouts"></span>
24
+ <span class="so-button-text"><?php esc_html_e('Layouts', 'siteorigin-panels') ?></span>
25
+ </a>
26
+
27
+ <?php if( !empty($post) ) : ?>
28
+
29
+ <a class="so-tool-button so-history" style="display: none" title="<?php esc_attr_e( 'Edit History', 'siteorigin-panels' ) ?>">
30
+ <span class="so-panels-icon so-panels-icon-history"></span>
31
+ <span class="so-button-text"><?php _e('History', 'siteorigin-panels') ?></span>
32
+ </a>
33
+
34
+ <a class="so-tool-button so-live-editor" style="display: none" title="<?php esc_html_e( 'Live Editor', 'siteorigin-panels' ) ?>">
35
+ <span class="so-panels-icon so-panels-icon-live-editor"></span>
36
+ <span class="so-button-text"><?php _e('Live Editor', 'siteorigin-panels') ?></span>
37
+ </a>
38
+
39
+ <?php endif; ?>
40
+
41
+ <?php if( SiteOrigin_Panels::display_premium_teaser() ) : ?>
42
+ <a class="so-tool-button so-learn" title="<?php echo esc_attr_e( 'Page Builder Addons', 'siteorigin-panels' ) ?>" href="<?php echo esc_url( SiteOrigin_Panels::premium_url() ) ?>" style="margin-left: 10px;">
43
+ <span class="so-panels-icon so-panels-icon-addons"></span>
44
+ <span class="so-button-text"><?php echo esc_html_e( 'Addons', 'siteorigin-panels' ) ?></span>
45
+ </a>
46
+ <?php endif; ?>
47
+
48
+ <?php if( SiteOrigin_Panels::display_learn_button() ) : ?>
49
+ <a class="so-tool-button so-learn" title="<?php echo esc_attr_e( 'Learn Page Builder', 'siteorigin-panels' ) ?>" href="#siteorigin-learn-page-builder-tips" style="margin-left: 10px;">
50
+ <span class="so-panels-icon so-panels-icon-learn"></span>
51
+ <span class="so-button-text"><?php echo esc_html_e( 'Learn', 'siteorigin-panels' ) ?></span>
52
+ </a>
53
+ <?php endif ?>
54
+
55
+ <a class="so-switch-to-standard"><?php _e('Revert to Editor', 'siteorigin-panels') ?></a>
56
+
57
+ </div>
58
+
59
+ <div class="so-rows-container">
60
+
61
+ </div>
62
+
63
+ <div class="so-panels-welcome-message">
64
+ <div class="so-message-wrapper">
65
+ <?php
66
+ printf(
67
+ __( 'Add a %s, %s or %s to get started. Read our %s if you need help.', 'siteorigin-panels' ),
68
+ "<a href='#' class='so-tool-button so-widget-add'>" . __( 'Widget', 'siteorigin-panels' ) . "</a>",
69
+ "<a href='#' class='so-tool-button so-row-add'>" . __( 'Row', 'siteorigin-panels' ) . "</a>",
70
+ "<a href='#' class='so-tool-button so-prebuilt-add'>" . __( 'Prebuilt Layout', 'siteorigin-panels' ) . "</a>",
71
+ "<a href='https://siteorigin.com/page-builder/documentation/' target='_blank' rel='noopener noreferrer'>" . __( 'documentation', 'siteorigin-panels' ) . "</a>"
72
+ );
73
+ ?>
74
+ </div>
75
+
76
+ <?php if( SiteOrigin_Panels::display_premium_teaser() ) : ?>
77
+ <div class="so-tip-wrapper">
78
+ <strong><?php _e( 'Pro Tip', 'siteorigin-panels' ) ?>: </strong>
79
+ <?php SiteOrigin_Panels_Admin::display_footer_premium_link() ?>
80
+ </div>
81
+ <?php endif; ?>
82
+ </div>
83
+
84
+ </div>
85
+
86
+ </script>
87
+
88
+ <script type="text/template" id="siteorigin-panels-builder-row">
89
+ <div class="so-row-container ui-draggable so-row-color-{{%= rowColorLabel %}}">
90
+
91
+ <div class="so-row-toolbar">
92
+ {{% if( rowLabel ) { %}}
93
+ <h3 class="so-row-label">{{%= rowLabel %}}</h3>
94
+ {{% } %}}
95
+ <span class="so-row-move so-tool-button"><span class="so-panels-icon so-panels-icon-move"></span></span>
96
+
97
+ <span class="so-dropdown-wrapper">
98
+ <a class="so-row-settings so-tool-button"><span class="so-panels-icon so-panels-icon-settings"></span></a>
99
+
100
+ <div class="so-dropdown-links-wrapper">
101
+ <ul>
102
+ <li><a class="so-row-settings"><?php _e('Edit Row', 'siteorigin-panels') ?></a></li>
103
+ <li><a class="so-row-duplicate"><?php _e('Duplicate Row', 'siteorigin-panels') ?></a></li>
104
+ <li><a class="so-row-delete so-needs-confirm" data-confirm="<?php esc_attr_e('Are you sure?', 'siteorigin-panels') ?>"><?php _e('Delete Row', 'siteorigin-panels') ?></a></li>
105
+ <li class="so-row-colors-container">
106
+ <?php
107
+ // See css/admin.less variable @row_colors. This should match the number of colors defined there.
108
+ $row_color_count = 5;
109
+
110
+ for ( $i = 1; $i <= $row_color_count; $i++ ) {
111
+ $classes = array( 'so-row-color', 'so-row-color-' . $i );
112
+
113
+ ?>
114
+ <div data-color-label="<?php echo esc_attr( $i ); ?>"
115
+ class="<?php echo esc_attr( implode( ' ', $classes ) ) ?>{{% if( rowColorLabel == '<?php echo esc_attr( $i ); ?>' ) print(' so-row-color-selected'); %}}"
116
+ ></div>
117
+ <?php
118
+ }
119
+ ?>
120
+ </li>
121
+ </ul>
122
+ <div class="so-pointer"></div>
123
+ </div>
124
+ </span>
125
+ </div>
126
+
127
+ <div class="so-cells">
128
+
129
+ </div>
130
+
131
+ </div>
132
+ </script>
133
+
134
+ <script type="text/template" id="siteorigin-panels-builder-cell">
135
+ <div class="cell">
136
+ <div class="resize-handle"></div>
137
+ <div class="cell-wrapper widgets-container">
138
+ </div>
139
+ </div>
140
+ </script>
141
+
142
+ <script type="text/template" id="siteorigin-panels-builder-widget">
143
+ <div class="so-widget ui-draggable">
144
+ <div class="so-widget-wrapper">
145
+ <div class="title">
146
+ <h4>{{%= title %}}</h4>
147
+ <span class="actions">
148
+ <a class="widget-edit"><?php _e('Edit', 'siteorigin-panels') ?></a>
149
+ <a class="widget-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
150
+ <a class="widget-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
151
+ </span>
152
+ </div>
153
+ <small class="description">{{%= description %}}</small>
154
+ </div>
155
+ </div>
156
+ </script>
157
+
158
+ <script type="text/template" id="siteorigin-panels-dialog">
159
+ <div class="so-panels-dialog {{% if(typeof left_sidebar != 'undefined') print('so-panels-dialog-has-left-sidebar '); if(typeof right_sidebar != 'undefined') print('so-panels-dialog-has-right-sidebar '); %}}">
160
+
161
+ <div class="so-overlay"></div>
162
+
163
+ <div class="so-title-bar {{% if ( dialogIcon ) print( 'so-has-icon' ) %}}">
164
+ {{% if ( ! _.isEmpty( dialogIcon ) ) { %}}
165
+ <div class="so-panels-icon so-panels-icon-{{%- dialogIcon %}}" />
166
+ {{% } %}}
167
+ <h3 class="so-title{{% if ( editableLabel ) print(' so-title-editable')%}}"
168
+ {{% if ( editableLabel ) print('contenteditable="true" spellcheck="false" tabIndex="1"')%}}
169
+ >{{%= title %}}</h3>
170
+ <a class="so-previous so-nav"><span class="so-dialog-icon"></span></a>
171
+ <a class="so-next so-nav"><span class="so-dialog-icon"></span></a>
172
+ <a class="so-close"><span class="so-dialog-icon"></span></a>
173
+ </div>
174
+
175
+ <div class="so-toolbar">
176
+ <div class="so-status">{{% if(typeof status != 'undefined') print(status); %}}</div>
177
+ <div class="so-buttons">
178
+ {{%= buttons %}}
179
+ </div>
180
+ </div>
181
+
182
+ <div class="so-sidebar so-left-sidebar">
183
+ {{% if(typeof left_sidebar != 'undefined') print(left_sidebar ); %}}
184
+ </div>
185
+
186
+ <div class="so-sidebar so-right-sidebar">
187
+ {{% if(typeof right_sidebar != 'undefined') print(right_sidebar ); %}}
188
+ </div>
189
+
190
+ <div class="so-content panel-dialog">
191
+ {{%= content %}}
192
+ </div>
193
+
194
+ </div>
195
+ </script>
196
+
197
+ <script type="text/template" id="siteorigin-panels-dialog-builder">
198
+ <div class="dialog-data">
199
+
200
+ <h3 class="title"><?php _e('Page Builder', 'siteorigin-panels') ?></h3>
201
+
202
+ <div class="content">
203
+ <div class="siteorigin-panels-builder">
204
+
205
+ </div>
206
+ </div>
207
+
208
+ <div class="buttons">
209
+ <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
210
+ </div>
211
+
212
+ </div>
213
+ </script>
214
+
215
+
216
+ <script type="text/template" id="siteorigin-panels-dialog-tab">
217
+ <li><a href="{{% if(typeof tab != 'undefined') { print ( '#' + tab ); } %}}">{{%= title %}}</a></li>
218
+ </script>
219
+
220
+ <script type="text/template" id="siteorigin-panels-dialog-widgets">
221
+ <div class="dialog-data">
222
+
223
+ <h3 class="title"><?php printf( __('Add New Widget %s', 'siteorigin-panels'), '<span class="current-tab-title"></span>' ) ?></h3>
224
+
225
+ <div class="left-sidebar">
226
+
227
+ <input type="text" class="so-sidebar-search" placeholder="<?php esc_attr_e('Search Widgets', 'siteorigin-panels') ?>" />
228
+
229
+ <ul class="so-sidebar-tabs">
230
+ </ul>
231
+
232
+ </div>
233
+
234
+ <div class="content">
235
+ <ul class="widget-type-list"></ul>
236
+ </div>
237
+
238
+ <div class="buttons">
239
+ <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Close', 'siteorigin-panels') ?>" />
240
+ </div>
241
+
242
+ </div>
243
+ </script>
244
+
245
+ <script type="text/template" id="siteorigin-panels-dialog-widgets-widget">
246
+ <li class="widget-type">
247
+ <div class="widget-type-wrapper">
248
+ <h3>{{%= title %}}</h3>
249
+ <small class="description">{{%= description %}}</small>
250
+ </div>
251
+ </li>
252
+ </script>
253
+
254
+ <script type="text/template" id="siteorigin-panels-dialog-widget">
255
+ <div class="dialog-data">
256
+
257
+ <h3 class="title"><span class="widget-name"></span></h3>
258
+
259
+ <div class="right-sidebar"></div>
260
+
261
+ <div class="content">
262
+
263
+ <div class="widget-form">
264
+ </div>
265
+
266
+ </div>
267
+
268
+ <div class="buttons">
269
+ <div class="action-buttons">
270
+ <a class="so-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
271
+ <a class="so-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
272
+ </div>
273
+
274
+ <input type="button" class="button-primary so-close" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
275
+ </div>
276
+
277
+ </div>
278
+ </script>
279
+
280
+ <script type="text/template" id="siteorigin-panels-dialog-widget-sidebar-widget">
281
+ <div class="so-widget">
282
+ <h3>{{%= title %}}</h3>
283
+ <small class="description">
284
+ {{%= description %}}
285
+ </small>
286
+ </div>
287
+ </script>
288
+
289
+ <script type="text/template" id="siteorigin-panels-dialog-row">
290
+ <div class="dialog-data">
291
+
292
+ <h3 class="title">
293
+ {{%= title %}}
294
+ </h3>
295
+
296
+ <div class="right-sidebar"></div>
297
+
298
+ <div class="content">
299
+
300
+ <div class="row-set-form">
301
+ <?php
302
+ $cells_field = apply_filters('siteorigin_panels_row_column_count_input', '<input type="number" min="1" max="12" name="cells" class="so-row-field" value="2" />');
303
+ $ratios = apply_filters('siteorigin_panels_column_ratios', array(
304
+ 'Even' => 1,
305
+ 'Golden' => 0.61803398,
306
+ 'Halves' => 0.5,
307
+ 'Thirds' => 0.33333333,
308
+ 'Diagon' => 0.41421356,
309
+ 'Hecton' => 0.73205080,
310
+ 'Hemidiagon' => 0.11803398,
311
+ 'Penton' => 0.27201964,
312
+ 'Trion' => 0.15470053,
313
+ 'Quadriagon' => 0.207,
314
+ 'Biauron' => 0.30901699,
315
+ 'Bipenton' => 0.46,
316
+ ) );
317
+ $ratio_field = '<select name="ratio" class="so-row-field">';
318
+ foreach( $ratios as $name => $value ) {
319
+ $ratio_field .= '<option value="' . esc_attr($value) . '">' . esc_html($name . ' (' . round($value, 3) . ')') . '</option>';
320
+ }
321
+ $ratio_field .= '</select>';
322
+
323
+ $direction_field = '<select name="ratio_direction" class="so-row-field">';
324
+ $direction_field .= '<option value="right">' . esc_html__('Left to Right', 'siteorigin-panels') . '</option>';
325
+ $direction_field .= '<option value="left">' . esc_html__('Right to Left', 'siteorigin-panels') . '</option>';
326
+ $direction_field .= '</select>';
327
+
328
+ printf(
329
+ preg_replace(
330
+ array(
331
+ '/1\{ *(.*?) *\}/',
332
+ ),
333
+ array(
334
+ '<strong>$1</strong>',
335
+ ),
336
+ __('1{Set row layout}: %1$s columns with a ratio of %2$s going from %3$s', 'siteorigin-panels')
337
+ ),
338
+ $cells_field,
339
+ $ratio_field,
340
+ $direction_field
341
+ );
342
+ echo '<button class="button-secondary set-row">' . esc_html__('Set', 'siteorigin-panels') . '</button>';
343
+ ?>
344
+ </div>
345
+
346
+ <div class="row-preview">
347
+
348
+ </div>
349
+
350
+ </div>
351
+
352
+ <div class="buttons">
353
+ {{% if( dialogType == 'edit' ) { %}}
354
+ <div class="action-buttons">
355
+ <a class="so-delete"><?php _e('Delete', 'siteorigin-panels') ?></a>
356
+ <a class="so-duplicate"><?php _e('Duplicate', 'siteorigin-panels') ?></a>
357
+ </div>
358
+ {{% } %}}
359
+
360
+ {{% if( dialogType == 'create' ) { %}}
361
+ <input type="button" class="button-primary so-insert" value="<?php esc_attr_e('Insert', 'siteorigin-panels') ?>" />
362
+ {{% } else { %}}
363
+ <input type="button" class="button-primary so-save" value="<?php esc_attr_e('Done', 'siteorigin-panels') ?>" />
364
+ {{% } %}}
365
+ </div>
366
+
367
+ </div>
368
+ </script>
369
+
370
+ <script type="text/template" id="siteorigin-panels-dialog-row-cell-preview">
371
+ <div class="preview-cell" style="width: {{%- weight*100 %}}%">
372
+ <div class="preview-cell-in">
373
+ <div class="preview-cell-weight">{{% print(Math.round(weight * 1000) / 10) %}}</div>
374
+ </div>
375
+ </div>
376
+ </script>
377
+
378
+ <script type="text/template" id="siteorigin-panels-dialog-prebuilt">
379
+ <div class="dialog-data">
380
+
381
+ <h3 class="title"><?php _e('Page Builder Layouts', 'siteorigin-panels') ?></h3>
382
+
383
+ <div class="left-sidebar">
384
+
385
+ <input type="text" class="so-sidebar-search" placeholder="<?php esc_attr_e('Search', 'siteorigin-panels') ?>" />
386
+
387
+ <ul class="so-sidebar-tabs">
388
+ <?php if( !empty( $layouts ) ) : ?>
389
+ <li>
390
+ <a href="#prebuilt"><?php _e('Prebuilt Layouts', 'siteorigin-panels') ?></a>
391
+ </li>
392
+ <?php endif; ?>
393
+
394
+ <?php
395
+ $directories = SiteOrigin_Panels_Admin_Layouts::single()->get_directories();
396
+ foreach ( $directories as $id => $directory ) {
397
+ ?><li><a href="#directory-<?php echo urlencode( $id ) ?>"><?php echo esc_html( $directory['title'] ) ?></a></li><?php
398
+ }
399
+ ?>
400
+ <li><a href="#import"><?php _e('Import/Export', 'siteorigin-panels') ?></a></li>
401
+
402
+ <?php
403
+ $post_types = siteorigin_panels_setting('post-types');
404
+ foreach($post_types as $post_type) {
405
+ $type = get_post_type_object( $post_type );
406
+ if( empty($type) ) continue;
407
+ ?><li><a href="#<?php echo 'clone_'.$post_type ?>"><?php printf( __('Clone: %s', 'siteorigin-panels'), $type->labels->name ) ?></a></li><?php
408
+ }
409
+ ?>
410
+ </ul>
411
+
412
+ </div>
413
+
414
+ <div class="content">
415
+ </div>
416
+
417
+ <div class="buttons">
418
+ <span class="so-dropdown-wrapper">
419
+ <input type="button" class="button-primary so-dropdown-button so-import-layout disabled" value="<?php esc_attr_e('Insert', 'siteorigin-panels') ?>" disabled="disabled"/>
420
+
421
+ <div class="so-dropdown-links-wrapper hidden">
422
+ <ul class="so-layout-position">
423
+ <li><a class="so-toolbar-button" data-value="after"><?php esc_html_e('Insert after', 'siteorigin-panels') ?></a></li>
424
+ <li><a class="so-toolbar-button" data-value="before"><?php esc_html_e('Insert before', 'siteorigin-panels') ?></a></li>
425
+ <li><a class="so-toolbar-button so-needs-confirm" data-value="replace" data-confirm="<?php esc_attr_e('Are you sure?', 'siteorigin-panels') ?>"><?php esc_html_e('Replace current', 'siteorigin-panels') ?></a></li>
426
+ </ul>
427
+ </div>
428
+ </span>
429
+ </div>
430
+
431
+ </div>
432
+ </script>
433
+
434
+ <script type="text/template" id="siteorigin-panels-directory-enable">
435
+ <div class="so-enable-prebuilt">
436
+ <?php _e('Do you want to browse the Prebuilt Layouts directory?', 'siteorigin-panels') ?>
437
+ <button class="button-primary so-panels-enable-directory"><?php _e('Enable', 'siteorigin-panels') ?></button>
438
+ </div>
439
+ </script>
440
+
441
+ <script type="text/template" id="siteorigin-panels-directory-items">
442
+ <div class="so-directory-items">
443
+
444
+ <div class="so-directory-browse">
445
+ </div>
446
+
447
+ <div class="so-directory-items-wrapper">
448
+ {{% if(items.length === 0) { %}}
449
+ <div class="so-no-results">
450
+ <?php _e( "Your search didn't return any results", 'siteorigin-panels' ); ?>
451
+ </div>
452
+ {{% } else { %}}
453
+ {{% _.each(items, function(item) { %}}
454
+ <div class="so-directory-item" data-layout-id="{{%- item.id %}}" data-layout-type="{{%- item.type %}}">
455
+ <div class="so-directory-item-wrapper">
456
+ <div class="so-screenshot" data-src="{{%- item.screenshot %}}">
457
+ <div class="so-panels-loading so-screenshot-wrapper"></div>
458
+ </div>
459
+ <div class="so-description">{{%- item.description %}}</div>
460
+
461
+ <div class="so-bottom">
462
+ <h4 class="so-title">{{%= item.title %}}</h4>
463
+ {{% if( item.preview ) { %}}
464
+ <div class="so-buttons">
465
+ <a href="{{%- item.preview %}}" class="button-secondary so-button-preview" target="_blank" rel="noopener noreferrer">Preview</a>
466
+ </div>
467
+ {{% } %}}
468
+ </div>
469
+ </div>
470
+ </div>
471
+ {{% }); %}}
472
+ {{% } %}}
473
+ </div>
474
+
475
+ <div class="clear"></div>
476
+
477
+ <div class="so-directory-pages">
478
+ <a class="so-previous button-secondary" data-direction="prev"><?php _e('Previous', 'siteorigin-panels') ?></a>
479
+ <a class="so-next button-secondary" data-direction="next"><?php _e('Next', 'siteorigin-panels') ?></a>
480
+ </div>
481
+ </div>
482
+ </script>
483
+
484
+ <script type="text/template" id="siteorigin-panels-dialog-prebuilt-importexport">
485
+ <div class="import-export">
486
+ <div class="import-upload-ui hide-if-no-js">
487
+ <div class="drag-upload-area">
488
+
489
+ <h2 class="drag-drop-message"><?php _e('Drop import file here', 'siteorigin-panels'); ?></h2>
490
+ <p class="drag-drop-message"><?php _e('Or', 'siteorigin-panels') ?></p>
491
+
492
+ <p class="drag-drop-buttons">
493
+ <input type="button" value="<?php esc_attr_e('Select Import File', 'siteorigin-panels'); ?>" class="file-browse-button button" />
494
+ </p>
495
+
496
+ <p class="drag-drop-message js-so-selected-file"></p>
497
+
498
+ <div class="progress-bar">
499
+ <div class="progress-percent"></div>
500
+ </div>
501
+ </div>
502
+ </div>
503
+
504
+ <div class="export-file-ui">
505
+ <iframe id="siteorigin-panels-export-iframe" style="display: none;" name="siteorigin-panels-export-iframe"></iframe>
506
+ <form action="<?php echo admin_url('admin-ajax.php?action=so_panels_export_layout') ?>" target="siteorigin-panels-export-iframe" class="so-export" method="post">
507
+ <input type="submit" value="<?php esc_attr_e('Download Layout', 'siteorigin-panels') ?>" class="button-primary" />
508
+ <input type="hidden" name="panels_export_data" value="" />
509
+ <?php wp_nonce_field('panels_action', '_panelsnonce') ?>
510
+ </form>
511
+ </div>
512
+ </div>
513
+ </script>
514
+
515
+ <script type="text/template" id="siteorigin-panels-dialog-history">
516
+ <div class="dialog-data">
517
+
518
+ <h3 class="title"><?php _e('Page Builder Change History', 'siteorigin-panels') ?></h3>
519
+
520
+ <div class="left-sidebar">
521
+ <div class="history-entries"></div>
522
+ </div>
523
+
524
+ <div class="content">
525
+ <form method="post" action="<?php echo SiteOrigin_Panels::preview_url() ?>" target="siteorigin-panels-history-iframe-{{%= cid %}}" class="history-form">
526
+ <input type="hidden" name="live_editor_panels_data" value="">
527
+ <input type="hidden" name="live_editor_post_ID" value="">
528
+ </form>
529
+ <iframe class="siteorigin-panels-history-iframe" name="siteorigin-panels-history-iframe-{{%= cid %}}" src=""></iframe>
530
+ </div>
531
+
532
+ <div class="buttons">
533
+ <input type="button" class="button-primary so-restore" value="<?php esc_attr_e('Restore Version', 'siteorigin-panels') ?>" />
534
+ </div>
535
+
536
+ </div>
537
+ </script>
538
+
539
+ <script type="text/template" id="siteorigin-panels-dialog-history-entry">
540
+ <div class="history-entry">
541
+ <h3>{{%= title %}}{{% if( count > 1 ) { %}} <span class="count">({{%= count %}})</span>{{% } %}}</h3>
542
+ <div class="timesince"></div>
543
+ </div>
544
+ </script>
545
+
546
+ <script type="text/template" id="siteorigin-panels-live-editor">
547
+ <div class="so-panels-live-editor">
548
+
549
+ <div class="live-editor-collapse">
550
+ <div class="collapse-icon"></div>
551
+ <span data-collapse="<?php esc_attr_e( 'Collapse', 'siteorigin-panels' ) ?>" data-expand="<?php esc_attr_e( 'Expand', 'siteorigin-panels' ) ?>">
552
+ <?php _e( 'Collapse', 'siteorigin-panels' ) ?>
553
+ </span>
554
+ </div>
555
+
556
+ <div class="so-sidebar-tools">
557
+ <button class="live-editor-close button-primary"><?php esc_html_e('Done', 'siteorigin-panels') ?></button>
558
+
559
+ <a class="live-editor-mode live-editor-desktop so-active" title="<?php esc_attr_e( 'Toggle desktop mode', 'siteorigin-panels' ) ?>" data-mode="desktop">
560
+ <span class="dashicons dashicons-desktop"></span>
561
+ </a>
562
+ <a class="live-editor-mode live-editor-tablet" title="<?php esc_attr_e( 'Toggle tablet mode', 'siteorigin-panels' ) ?>" data-mode="tablet">
563
+ <span class="dashicons dashicons-tablet"></span>
564
+ </a>
565
+ <a class="live-editor-mode live-editor-mobile" title="<?php esc_attr_e( 'Toggle mobile mode', 'siteorigin-panels' ) ?>" data-mode="mobile">
566
+ <span class="dashicons dashicons-smartphone"></span>
567
+ </a>
568
+
569
+ </div>
570
+
571
+ <div class="so-sidebar">
572
+ <div class="so-live-editor-builder"></div>
573
+ </div>
574
+
575
+ <div class="so-preview"></div>
576
+
577
+ <div class="so-preview-overlay">
578
+ <div class="so-loading-container"><div class="so-loading-bar"></div></div>
579
+ </div>
580
+
581
+ </div>
582
+ </script>
583
+
584
+ <script type="text/template" id="siteorigin-panels-context-menu">
585
+ <div class="so-panels-contextual-menu"></div>
586
+ </script>
587
+
588
+ <script type="text/template" id="siteorigin-panels-context-menu-section">
589
+ <div class="so-section">
590
+ <h5>{{%- settings.sectionTitle %}}</h5>
591
+
592
+ {{% if( settings.search ) { %}}
593
+ <div class="so-search-wrapper">
594
+ <input type="text" placeholder="{{%- settings.searchPlaceholder %}}" />
595
+ </div>
596
+ {{% } %}}
597
+ <ul class="so-items">
598
+ {{% for( var k in items ) { %}}
599
+ <li data-key="{{%- k %}}" class="so-item {{% if( !_.isUndefined( items[k].confirm ) && items[k].confirm ) { print( 'so-confirm' ); } %}}">{{%= items[k][settings.titleKey] %}}</li>
600
+ {{% } %}}
601
+ </ul>
602
+ {{% if( settings.search ) { %}}
603
+ <div class="so-no-results">
604
+ <?php _e('No Results', 'siteorigin-panels') ?>
605
+ </div>
606
+ {{% } %}}
607
+ </div>
608
+ </script>
tpl/live-editor-preview.php CHANGED
@@ -1,38 +1,38 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly.
4
- }
5
- wp_enqueue_style( 'siteorigin-preview-style', siteorigin_panels_url( 'css/live-editor-preview.css' ), array(), SITEORIGIN_PANELS_VERSION );
6
- ?>
7
- <!DOCTYPE html>
8
- <html <?php language_attributes(); ?>>
9
- <head>
10
- <meta charset="<?php bloginfo( 'charset' ); ?>">
11
- <meta name="viewport" content="width=device-width, initial-scale=1">
12
- <link rel="profile" href="http://gmpg.org/xfn/11">
13
- <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
14
- <?php wp_head(); ?>
15
- </head>
16
-
17
- <body <?php body_class(); ?>>
18
- <div id="content" class="site-content">
19
- <div class="entry-content">
20
- <?php
21
- if( !empty( $_POST['live_editor_panels_data'] ) ) {
22
- $data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
23
- if(
24
- !empty( $data['widgets'] ) && (
25
- !class_exists( 'SiteOrigin_Widget_Field_Class_Loader' ) ||
26
- method_exists( 'SiteOrigin_Widget_Field_Class_Loader', 'extend' )
27
- )
28
- ) {
29
- $data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $data['widgets'], false, false );
30
- }
31
- echo siteorigin_panels_render( 'l' . md5( serialize( $data ) ), true, $data);
32
- }
33
- ?>
34
- </div><!-- .entry-content -->
35
- </div>
36
- <?php wp_footer(); ?>
37
- </body>
38
- </html>
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly.
4
+ }
5
+ wp_enqueue_style( 'siteorigin-preview-style', siteorigin_panels_url( 'css/live-editor-preview' . SITEORIGIN_PANELS_CSS_SUFFIX . '.css' ), array(), SITEORIGIN_PANELS_VERSION );
6
+ ?>
7
+ <!DOCTYPE html>
8
+ <html <?php language_attributes(); ?>>
9
+ <head>
10
+ <meta charset="<?php bloginfo( 'charset' ); ?>">
11
+ <meta name="viewport" content="width=device-width, initial-scale=1">
12
+ <link rel="profile" href="http://gmpg.org/xfn/11">
13
+ <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
14
+ <?php wp_head(); ?>
15
+ </head>
16
+
17
+ <body <?php body_class(); ?>>
18
+ <div id="content" class="site-content">
19
+ <div class="entry-content">
20
+ <?php
21
+ if( !empty( $_POST['live_editor_panels_data'] ) ) {
22
+ $data = json_decode( wp_unslash( $_POST['live_editor_panels_data'] ), true );
23
+ if(
24
+ !empty( $data['widgets'] ) && (
25
+ !class_exists( 'SiteOrigin_Widget_Field_Class_Loader' ) ||
26
+ method_exists( 'SiteOrigin_Widget_Field_Class_Loader', 'extend' )
27
+ )
28
+ ) {
29
+ $data['widgets'] = SiteOrigin_Panels_Admin::single()->process_raw_widgets( $data['widgets'], false, false );
30
+ }
31
+ echo siteorigin_panels_render( 'l' . md5( serialize( $data ) ), true, $data);
32
+ }
33
+ ?>
34
+ </div><!-- .entry-content -->
35
+ </div>
36
+ <?php wp_footer(); ?>
37
+ </body>
38
+ </html>