Page Builder by SiteOrigin - Version 2.6.4

Version Description

  • 4 April 2018 =
  • Only call widget enqueue_admin_scripts function for WP core JS widgets.
Download this release

Release Info

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

Code changes from version 2.6.3 to 2.6.4

inc/admin.php CHANGED
@@ -445,14 +445,14 @@ class SiteOrigin_Panels_Admin {
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
  }
@@ -885,12 +885,12 @@ class SiteOrigin_Panels_Admin {
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 ); ?>" />
@@ -909,7 +909,7 @@ class SiteOrigin_Panels_Admin {
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',
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 ( $this->is_core_js_widget( $widget_obj ) && 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_core_js_widget( $widget_obj ) ) {
456
  $js_widgets[] = $widget_obj;
457
  }
458
  }
885
  $the_widget->number = $widget_number;
886
 
887
  ob_start();
888
+ if ( $this->is_core_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_core_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 ); ?>" />
909
  return $form;
910
  }
911
 
912
+ function is_core_js_widget( $widget ) {
913
  $js_widgets = array(
914
  'WP_Widget_Custom_HTML',
915
  'WP_Widget_Media_Audio',
js/siteorigin-panels-264.js ADDED
@@ -0,0 +1,7261 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ var panels = window.panels;
3
+
4
+ module.exports = Backbone.Collection.extend( {
5
+ model: panels.model.cell,
6
+
7
+ initialize: function () {
8
+ },
9
+
10
+ /**
11
+ * Get the total weight for the cells in this collection.
12
+ * @returns {number}
13
+ */
14
+ totalWeight: function () {
15
+ var totalWeight = 0;
16
+ this.each( function ( cell ) {
17
+ totalWeight += cell.get( 'weight' );
18
+ } );
19
+
20
+ return totalWeight;
21
+ },
22
+
23
+ } );
24
+
25
+ },{}],2:[function(require,module,exports){
26
+ var panels = window.panels;
27
+
28
+ module.exports = Backbone.Collection.extend( {
29
+ model: panels.model.historyEntry,
30
+
31
+ /**
32
+ * The builder model
33
+ */
34
+ builder: null,
35
+
36
+ /**
37
+ * The maximum number of items in the history
38
+ */
39
+ maxSize: 12,
40
+
41
+ initialize: function () {
42
+ this.on( 'add', this.onAddEntry, this );
43
+ },
44
+
45
+ /**
46
+ * Add an entry to the collection.
47
+ *
48
+ * @param text The text that defines the action taken to get to this
49
+ * @param data
50
+ */
51
+ addEntry: function ( text, data ) {
52
+
53
+ if ( _.isEmpty( data ) ) {
54
+ data = this.builder.getPanelsData();
55
+ }
56
+
57
+ var entry = new panels.model.historyEntry( {
58
+ text: text,
59
+ data: JSON.stringify( data ),
60
+ time: parseInt( new Date().getTime() / 1000 ),
61
+ collection: this
62
+ } );
63
+
64
+ this.add( entry );
65
+ },
66
+
67
+ /**
68
+ * Resize the collection so it's not bigger than this.maxSize
69
+ */
70
+ onAddEntry: function ( entry ) {
71
+
72
+ if ( this.models.length > 1 ) {
73
+ var lastEntry = this.at( this.models.length - 2 );
74
+
75
+ if (
76
+ (
77
+ entry.get( 'text' ) === lastEntry.get( 'text' ) && entry.get( 'time' ) - lastEntry.get( 'time' ) < 15
78
+ ) ||
79
+ (
80
+ entry.get( 'data' ) === lastEntry.get( 'data' )
81
+ )
82
+ ) {
83
+ // If both entries have the same text and are within 20 seconds of each other, or have the same data, then remove most recent
84
+ this.remove( entry );
85
+ lastEntry.set( 'count', lastEntry.get( 'count' ) + 1 );
86
+ }
87
+ }
88
+
89
+ // Make sure that there are not to many entries in this collection
90
+ while ( this.models.length > this.maxSize ) {
91
+ this.shift();
92
+ }
93
+ }
94
+ } );
95
+
96
+ },{}],3:[function(require,module,exports){
97
+ var panels = window.panels;
98
+
99
+ module.exports = Backbone.Collection.extend( {
100
+ model: panels.model.row,
101
+
102
+ /**
103
+ * Destroy all the rows in this collection
104
+ */
105
+ empty: function () {
106
+ var model;
107
+ do {
108
+ model = this.collection.first();
109
+ if ( ! model ) {
110
+ break;
111
+ }
112
+
113
+ model.destroy();
114
+ } while ( true );
115
+ }
116
+
117
+ } );
118
+
119
+ },{}],4:[function(require,module,exports){
120
+ var panels = window.panels;
121
+
122
+ module.exports = Backbone.Collection.extend( {
123
+ model: panels.model.widget,
124
+
125
+ initialize: function () {
126
+
127
+ }
128
+
129
+ } );
130
+
131
+ },{}],5:[function(require,module,exports){
132
+ var panels = window.panels, $ = jQuery;
133
+
134
+ module.exports = panels.view.dialog.extend( {
135
+ dialogClass: 'so-panels-dialog-add-builder',
136
+
137
+ render: function () {
138
+ // Render the dialog and attach it to the builder interface
139
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-builder' ).html(), {} ) );
140
+ this.$( '.so-content .siteorigin-panels-builder' ).append( this.builder.$el );
141
+ },
142
+
143
+ initializeDialog: function () {
144
+ var thisView = this;
145
+ this.once( 'open_dialog_complete', function () {
146
+ thisView.builder.initSortable();
147
+ } );
148
+
149
+ this.on( 'open_dialog_complete', function () {
150
+ thisView.builder.trigger( 'builder_resize' );
151
+ } );
152
+ }
153
+ } );
154
+
155
+ },{}],6:[function(require,module,exports){
156
+ var panels = window.panels, $ = jQuery;
157
+
158
+ module.exports = panels.view.dialog.extend( {
159
+
160
+ historyEntryTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-history-entry' ).html() ) ),
161
+
162
+ entries: {},
163
+ currentEntry: null,
164
+ revertEntry: null,
165
+ selectedEntry: null,
166
+
167
+ previewScrollTop: null,
168
+
169
+ dialogClass: 'so-panels-dialog-history',
170
+ dialogIcon: 'history',
171
+
172
+ events: {
173
+ 'click .so-close': 'closeDialog',
174
+ 'click .so-restore': 'restoreSelectedEntry'
175
+ },
176
+
177
+ initializeDialog: function () {
178
+ this.entries = new panels.collection.historyEntries();
179
+
180
+ this.on( 'open_dialog', this.setCurrentEntry, this );
181
+ this.on( 'open_dialog', this.renderHistoryEntries, this );
182
+ },
183
+
184
+ render: function () {
185
+ var thisView = this;
186
+
187
+ // Render the dialog and attach it to the builder interface
188
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-history' ).html(), {} ) );
189
+
190
+ this.$( 'iframe.siteorigin-panels-history-iframe' ).load( function () {
191
+ var $$ = $( this );
192
+ $$.show();
193
+
194
+ $$.contents().scrollTop( thisView.previewScrollTop );
195
+ } );
196
+ },
197
+
198
+ /**
199
+ * Set the original entry. This should be set when creating the dialog.
200
+ *
201
+ * @param {panels.model.builder} builder
202
+ */
203
+ setRevertEntry: function ( builder ) {
204
+ this.revertEntry = new panels.model.historyEntry( {
205
+ data: JSON.stringify( builder.getPanelsData() ),
206
+ time: parseInt( new Date().getTime() / 1000 )
207
+ } );
208
+ },
209
+
210
+ /**
211
+ * This is triggered when the dialog is opened.
212
+ */
213
+ setCurrentEntry: function () {
214
+ this.currentEntry = new panels.model.historyEntry( {
215
+ data: JSON.stringify( this.builder.model.getPanelsData() ),
216
+ time: parseInt( new Date().getTime() / 1000 )
217
+ } );
218
+
219
+ this.selectedEntry = this.currentEntry;
220
+ this.previewEntry( this.currentEntry );
221
+ this.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
222
+ },
223
+
224
+ /**
225
+ * Render the history entries in the sidebar
226
+ */
227
+ renderHistoryEntries: function () {
228
+ // Set up an interval that will display the time since every 10 seconds
229
+ var thisView = this;
230
+
231
+ var c = this.$( '.history-entries' ).empty();
232
+
233
+ if ( this.currentEntry.get( 'data' ) !== this.revertEntry.get( 'data' ) || ! _.isEmpty( this.entries.models ) ) {
234
+ $( this.historyEntryTemplate( {title: panelsOptions.loc.history.revert, count: 1} ) )
235
+ .data( 'historyEntry', this.revertEntry )
236
+ .prependTo( c );
237
+ }
238
+
239
+ // Now load all the entries in this.entries
240
+ this.entries.each( function ( entry ) {
241
+
242
+ var html = thisView.historyEntryTemplate( {
243
+ title: panelsOptions.loc.history[entry.get( 'text' )],
244
+ count: entry.get( 'count' )
245
+ } );
246
+
247
+ $( html )
248
+ .data( 'historyEntry', entry )
249
+ .prependTo( c );
250
+ } );
251
+
252
+
253
+ $( this.historyEntryTemplate( {title: panelsOptions.loc.history['current'], count: 1} ) )
254
+ .data( 'historyEntry', this.currentEntry )
255
+ .addClass( 'so-selected' )
256
+ .prependTo( c );
257
+
258
+ // Handle loading and selecting
259
+ c.find( '.history-entry' ).click( function () {
260
+ var $$ = jQuery( this );
261
+ c.find( '.history-entry' ).not( $$ ).removeClass( 'so-selected' );
262
+ $$.addClass( 'so-selected' );
263
+
264
+ var entry = $$.data( 'historyEntry' );
265
+
266
+ thisView.selectedEntry = entry;
267
+
268
+ if ( thisView.selectedEntry.cid !== thisView.currentEntry.cid ) {
269
+ thisView.$( '.so-buttons .so-restore' ).removeClass( 'disabled' );
270
+ } else {
271
+ thisView.$( '.so-buttons .so-restore' ).addClass( 'disabled' );
272
+ }
273
+
274
+ thisView.previewEntry( entry );
275
+ } );
276
+
277
+ this.updateEntryTimes();
278
+ },
279
+
280
+ /**
281
+ * Preview an entry
282
+ *
283
+ * @param entry
284
+ */
285
+ previewEntry: function ( entry ) {
286
+ var iframe = this.$( 'iframe.siteorigin-panels-history-iframe' );
287
+ iframe.hide();
288
+ this.previewScrollTop = iframe.contents().scrollTop();
289
+
290
+ this.$( 'form.history-form input[name="live_editor_panels_data"]' ).val( entry.get( 'data' ) );
291
+ this.$( 'form.history-form input[name="live_editor_post_ID"]' ).val( this.builder.config.postId );
292
+ this.$( 'form.history-form' ).submit();
293
+ },
294
+
295
+ /**
296
+ * Restore the current entry
297
+ */
298
+ restoreSelectedEntry: function () {
299
+
300
+ if ( this.$( '.so-buttons .so-restore' ).hasClass( 'disabled' ) ) {
301
+ return false;
302
+ }
303
+
304
+ if ( this.currentEntry.get( 'data' ) === this.selectedEntry.get( 'data' ) ) {
305
+ this.closeDialog();
306
+ return false;
307
+ }
308
+
309
+ // Add an entry for this restore event
310
+ if ( this.selectedEntry.get( 'text' ) !== 'restore' ) {
311
+ this.builder.addHistoryEntry( 'restore', this.builder.model.getPanelsData() );
312
+ }
313
+
314
+ this.builder.model.loadPanelsData( JSON.parse( this.selectedEntry.get( 'data' ) ) );
315
+
316
+ this.closeDialog();
317
+
318
+ return false;
319
+ },
320
+
321
+ /**
322
+ * Update the entry times for the list of entries down the side
323
+ */
324
+ updateEntryTimes: function () {
325
+ var thisView = this;
326
+
327
+ this.$( '.history-entries .history-entry' ).each( function () {
328
+ var $$ = jQuery( this );
329
+
330
+ var time = $$.find( '.timesince' );
331
+ var entry = $$.data( 'historyEntry' );
332
+
333
+ time.html( thisView.timeSince( entry.get( 'time' ) ) );
334
+ } );
335
+ },
336
+
337
+ /**
338
+ * Gets the time since as a nice string.
339
+ *
340
+ * @param date
341
+ */
342
+ timeSince: function ( time ) {
343
+ var diff = parseInt( new Date().getTime() / 1000 ) - time;
344
+
345
+ var parts = [];
346
+ var interval;
347
+
348
+ // There are 3600 seconds in an hour
349
+ if ( diff > 3600 ) {
350
+ interval = Math.floor( diff / 3600 );
351
+ if ( interval === 1 ) {
352
+ parts.push( panelsOptions.loc.time.hour.replace( '%d', interval ) );
353
+ } else {
354
+ parts.push( panelsOptions.loc.time.hours.replace( '%d', interval ) );
355
+ }
356
+ diff -= interval * 3600;
357
+ }
358
+
359
+ // There are 60 seconds in a minute
360
+ if ( diff > 60 ) {
361
+ interval = Math.floor( diff / 60 );
362
+ if ( interval === 1 ) {
363
+ parts.push( panelsOptions.loc.time.minute.replace( '%d', interval ) );
364
+ } else {
365
+ parts.push( panelsOptions.loc.time.minutes.replace( '%d', interval ) );
366
+ }
367
+ diff -= interval * 60;
368
+ }
369
+
370
+ if ( diff > 0 ) {
371
+ if ( diff === 1 ) {
372
+ parts.push( panelsOptions.loc.time.second.replace( '%d', diff ) );
373
+ } else {
374
+ parts.push( panelsOptions.loc.time.seconds.replace( '%d', diff ) );
375
+ }
376
+ }
377
+
378
+ // Return the amount of time ago
379
+ return _.isEmpty( parts ) ? panelsOptions.loc.time.now : panelsOptions.loc.time.ago.replace( '%s', parts.slice( 0, 2 ).join( ', ' ) );
380
+
381
+ }
382
+
383
+ } );
384
+
385
+ },{}],7:[function(require,module,exports){
386
+ var panels = window.panels, $ = jQuery;
387
+
388
+ module.exports = panels.view.dialog.extend( {
389
+
390
+ directoryTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-directory-items' ).html() ) ),
391
+
392
+ builder: null,
393
+ dialogClass: 'so-panels-dialog-prebuilt-layouts',
394
+ dialogIcon: 'layouts',
395
+
396
+ layoutCache: {},
397
+ currentTab: false,
398
+ directoryPage: 1,
399
+
400
+ events: {
401
+ 'click .so-close': 'closeDialog',
402
+ 'click .so-sidebar-tabs li a': 'tabClickHandler',
403
+ 'click .so-content .layout': 'layoutClickHandler',
404
+ 'keyup .so-sidebar-search': 'searchHandler',
405
+
406
+ // The directory items
407
+ 'click .so-screenshot, .so-title': 'directoryItemClickHandler'
408
+ },
409
+
410
+ /**
411
+ * Initialize the prebuilt dialog.
412
+ */
413
+ initializeDialog: function () {
414
+ var thisView = this;
415
+
416
+ this.on( 'open_dialog', function () {
417
+ thisView.$( '.so-sidebar-tabs li a' ).first().click();
418
+ thisView.$( '.so-status' ).removeClass( 'so-panels-loading' );
419
+ } );
420
+
421
+ this.on( 'button_click', this.toolbarButtonClick, this );
422
+ },
423
+
424
+ /**
425
+ * Render the prebuilt layouts dialog
426
+ */
427
+ render: function () {
428
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-prebuilt' ).html(), {} ) );
429
+
430
+ this.initToolbar();
431
+ },
432
+
433
+ /**
434
+ *
435
+ * @param e
436
+ * @return {boolean}
437
+ */
438
+ tabClickHandler: function ( e ) {
439
+ e.preventDefault();
440
+ // Reset selected item state when changing tabs
441
+ this.selectedLayoutItem = null;
442
+ this.uploadedLayout = null;
443
+ this.updateButtonState( false );
444
+
445
+ this.$( '.so-sidebar-tabs li' ).removeClass( 'tab-active' );
446
+
447
+ var $$ = $( e.target );
448
+ var tab = $$.attr( 'href' ).split( '#' )[1];
449
+ $$.parent().addClass( 'tab-active' );
450
+
451
+ var thisView = this;
452
+
453
+ // Empty everything
454
+ this.$( '.so-content' ).empty();
455
+
456
+ thisView.currentTab = tab;
457
+ if ( tab == 'import' ) {
458
+ this.displayImportExport();
459
+ } else {
460
+ this.displayLayoutDirectory( '', 1, tab );
461
+ }
462
+
463
+ thisView.$( '.so-sidebar-search' ).val( '' );
464
+ },
465
+
466
+ /**
467
+ * Display and setup the import/export form
468
+ */
469
+ displayImportExport: function () {
470
+ var c = this.$( '.so-content' ).empty().removeClass( 'so-panels-loading' );
471
+ c.html( $( '#siteorigin-panels-dialog-prebuilt-importexport' ).html() );
472
+
473
+ var thisView = this;
474
+ var uploadUi = thisView.$( '.import-upload-ui' ).hide();
475
+
476
+ // Create the uploader
477
+ var uploader = new plupload.Uploader( {
478
+ runtimes: 'html5,silverlight,flash,html4',
479
+
480
+ browse_button: uploadUi.find( '.file-browse-button' ).get( 0 ),
481
+ container: uploadUi.get( 0 ),
482
+ drop_element: uploadUi.find( '.drag-upload-area' ).get( 0 ),
483
+
484
+ file_data_name: 'panels_import_data',
485
+ multiple_queues: false,
486
+ max_file_size: panelsOptions.plupload.max_file_size,
487
+ url: panelsOptions.plupload.url,
488
+ flash_swf_url: panelsOptions.plupload.flash_swf_url,
489
+ silverlight_xap_url: panelsOptions.plupload.silverlight_xap_url,
490
+ filters: [
491
+ {title: panelsOptions.plupload.filter_title, extensions: 'json'}
492
+ ],
493
+
494
+ multipart_params: {
495
+ action: 'so_panels_import_layout'
496
+ },
497
+
498
+ init: {
499
+ PostInit: function ( uploader ) {
500
+ if ( uploader.features.dragdrop ) {
501
+ uploadUi.addClass( 'has-drag-drop' );
502
+ }
503
+ uploadUi.show().find( '.progress-precent' ).css( 'width', '0%' );
504
+ },
505
+ FilesAdded: function ( uploader ) {
506
+ uploadUi.find( '.file-browse-button' ).blur();
507
+ uploadUi.find( '.drag-upload-area' ).removeClass( 'file-dragover' );
508
+ uploadUi.find( '.progress-bar' ).fadeIn( 'fast' );
509
+ thisView.$( '.js-so-selected-file' ).text( panelsOptions.loc.prebuilt_loading );
510
+ uploader.start();
511
+ },
512
+ UploadProgress: function ( uploader, file ) {
513
+ uploadUi.find( '.progress-precent' ).css( 'width', file.percent + '%' );
514
+ },
515
+ FileUploaded: function ( uploader, file, response ) {
516
+ var layout = JSON.parse( response.response );
517
+ if ( ! _.isUndefined( layout.widgets ) ) {
518
+
519
+ thisView.uploadedLayout = layout;
520
+ uploadUi.find( '.progress-bar' ).hide();
521
+ thisView.$( '.js-so-selected-file' ).text(
522
+ panelsOptions.loc.ready_to_insert.replace( '%s', file.name )
523
+ );
524
+ thisView.updateButtonState( true );
525
+ } else {
526
+ alert( panelsOptions.plupload.error_message );
527
+ }
528
+ },
529
+ Error: function () {
530
+ alert( panelsOptions.plupload.error_message );
531
+ }
532
+ }
533
+ } );
534
+ uploader.init();
535
+
536
+ // This is
537
+ uploadUi.find( '.drag-upload-area' )
538
+ .on( 'dragover', function () {
539
+ $( this ).addClass( 'file-dragover' );
540
+ } )
541
+ .on( 'dragleave', function () {
542
+ $( this ).removeClass( 'file-dragover' );
543
+ } );
544
+
545
+ // Handle exporting the file
546
+ c.find( '.so-export' ).submit( function ( e ) {
547
+ var $$ = $( this );
548
+ var panelsData = thisView.builder.model.getPanelsData();
549
+ var postName = $('input[name="post_title"]').val();
550
+ if ( ! postName ) {
551
+ postName = $('input[name="post_ID"]').val();
552
+ }
553
+ panelsData.name = postName;
554
+ $$.find( 'input[name="panels_export_data"]' ).val( JSON.stringify( panelsData ) );
555
+ } );
556
+
557
+ },
558
+
559
+ /**
560
+ * Display the layout directory tab.
561
+ *
562
+ * @param query
563
+ */
564
+ displayLayoutDirectory: function ( search, page, type ) {
565
+ var thisView = this;
566
+ var c = this.$( '.so-content' ).empty().addClass( 'so-panels-loading' );
567
+
568
+ if ( search === undefined ) {
569
+ search = '';
570
+ }
571
+ if ( page === undefined ) {
572
+ page = 1;
573
+ }
574
+ if ( type === undefined ) {
575
+ type = 'directory-siteorigin';
576
+ }
577
+
578
+ if ( type.match('^directory-') && ! panelsOptions.directory_enabled ) {
579
+ // Display the button to enable the prebuilt layout
580
+ c.removeClass( 'so-panels-loading' ).html( $( '#siteorigin-panels-directory-enable' ).html() );
581
+ c.find( '.so-panels-enable-directory' ).click( function ( e ) {
582
+ e.preventDefault();
583
+ // Sent the query to enable the directory, then enable the directory
584
+ $.get(
585
+ panelsOptions.ajaxurl,
586
+ {action: 'so_panels_directory_enable'},
587
+ function () {
588
+
589
+ }
590
+ );
591
+
592
+ // Enable the layout directory
593
+ panelsOptions.directory_enabled = true;
594
+ c.addClass( 'so-panels-loading' );
595
+ thisView.displayLayoutDirectory( search, page, type );
596
+ } );
597
+ return;
598
+ }
599
+
600
+ // Get all the items for the current query
601
+ $.get(
602
+ panelsOptions.ajaxurl,
603
+ {
604
+ action: 'so_panels_layouts_query',
605
+ search: search,
606
+ page: page,
607
+ type: type,
608
+ },
609
+ function ( data ) {
610
+ // Skip this if we're no longer viewing the layout directory
611
+ if ( thisView.currentTab !== type ) {
612
+ return;
613
+ }
614
+
615
+ // Add the directory items
616
+ c.removeClass( 'so-panels-loading' ).html( thisView.directoryTemplate( data ) );
617
+
618
+ // Lets setup the next and previous buttons
619
+ var prev = c.find( '.so-previous' ), next = c.find( '.so-next' );
620
+
621
+ if ( page <= 1 ) {
622
+ prev.addClass( 'button-disabled' );
623
+ } else {
624
+ prev.click( function ( e ) {
625
+ e.preventDefault();
626
+ thisView.displayLayoutDirectory( search, page - 1, thisView.currentTab );
627
+ } );
628
+ }
629
+
630
+ if ( page === data.max_num_pages || data.max_num_pages === 0 ) {
631
+ next.addClass( 'button-disabled' );
632
+ } else {
633
+ next.click( function ( e ) {
634
+ e.preventDefault();
635
+ thisView.displayLayoutDirectory( search, page + 1, thisView.currentTab );
636
+ } );
637
+ }
638
+
639
+ // Handle nice preloading of the screenshots
640
+ c.find( '.so-screenshot' ).each( function () {
641
+ var $$ = $( this ), $a = $$.find( '.so-screenshot-wrapper' );
642
+ $a.css( 'height', ( $a.width() / 4 * 3 ) + 'px' ).addClass( 'so-loading' );
643
+
644
+ if ( $$.data( 'src' ) !== '' ) {
645
+ // Set the initial height
646
+ var $img = $( '<img/>' ).attr( 'src', $$.data( 'src' ) ).load( function () {
647
+ $a.removeClass( 'so-loading' ).css( 'height', 'auto' );
648
+ $img.appendTo( $a ).hide().fadeIn( 'fast' );
649
+ } );
650
+ } else {
651
+ $( '<img/>' ).attr( 'src', panelsOptions.prebuiltDefaultScreenshot ).appendTo( $a ).hide().fadeIn( 'fast' );
652
+ }
653
+
654
+ } );
655
+
656
+ // Set the title
657
+ c.find( '.so-directory-browse' ).html( data.title );
658
+ },
659
+ 'json'
660
+ );
661
+ },
662
+
663
+ /**
664
+ * Set the selected state for the clicked layout directory item and remove previously selected item.
665
+ * Enable the toolbar buttons.
666
+ */
667
+ directoryItemClickHandler: function ( e ) {
668
+ var $directoryItem = this.$( e.target ).closest( '.so-directory-item' );
669
+ this.$( '.so-directory-items' ).find( '.selected' ).removeClass( 'selected' );
670
+ $directoryItem.addClass( 'selected' );
671
+ this.selectedLayoutItem = {lid: $directoryItem.data( 'layout-id' ), type: $directoryItem.data( 'layout-type' )};
672
+ this.updateButtonState( true );
673
+
674
+ },
675
+
676
+ /**
677
+ * Load a particular layout into the builder.
678
+ *
679
+ * @param id
680
+ */
681
+ toolbarButtonClick: function ( $button ) {
682
+ if ( ! this.canAddLayout() ) {
683
+ return false;
684
+ }
685
+ var position = $button.data( 'value' );
686
+ if ( _.isUndefined( position ) ) {
687
+ return false;
688
+ }
689
+ this.updateButtonState( false );
690
+
691
+ if ( $button.hasClass( 'so-needs-confirm' ) && ! $button.hasClass( 'so-confirmed' ) ) {
692
+ this.updateButtonState( true );
693
+ if ( $button.hasClass( 'so-confirming' ) ) {
694
+ return;
695
+ }
696
+ $button.addClass( 'so-confirming' );
697
+ var originalText = $button.html();
698
+ $button.html( '<span class="dashicons dashicons-yes"></span>' + $button.data( 'confirm' ) );
699
+ setTimeout( function () {
700
+ $button.removeClass( 'so-confirmed' ).html( originalText );
701
+ }, 2500 );
702
+ setTimeout( function () {
703
+ $button.removeClass( 'so-confirming' );
704
+ $button.addClass( 'so-confirmed' );
705
+ }, 200 );
706
+ return false;
707
+ }
708
+ this.addingLayout = true;
709
+ if ( this.currentTab === 'import' ) {
710
+ this.addLayoutToBuilder( this.uploadedLayout, position );
711
+ } else {
712
+ this.loadSelectedLayout().then( function ( layout ) {
713
+ this.addLayoutToBuilder( layout, position );
714
+ }.bind( this ) );
715
+ }
716
+ },
717
+
718
+ canAddLayout: function () {
719
+ return (
720
+ this.selectedLayoutItem || this.uploadedLayout
721
+ ) && ! this.addingLayout;
722
+ },
723
+
724
+ /**
725
+ * Load the layout according to selectedLayoutItem.
726
+ */
727
+ loadSelectedLayout: function () {
728
+ this.setStatusMessage( panelsOptions.loc.prebuilt_loading, true );
729
+
730
+ var args = _.extend( this.selectedLayoutItem, {action: 'so_panels_get_layout'} );
731
+ var deferredLayout = new $.Deferred();
732
+
733
+ $.get(
734
+ panelsOptions.ajaxurl,
735
+ args,
736
+ function ( layout ) {
737
+ var msg = '';
738
+ if ( ! layout.success ) {
739
+ msg = layout.data.message;
740
+ deferredLayout.reject( layout.data );
741
+ } else {
742
+ deferredLayout.resolve( layout.data );
743
+ }
744
+ this.setStatusMessage( msg, false, ! layout.success );
745
+ this.updateButtonState( true );
746
+ }.bind( this )
747
+ );
748
+ return deferredLayout.promise();
749
+ },
750
+
751
+ /**
752
+ * Handle an update to the search
753
+ */
754
+ searchHandler: function ( e ) {
755
+ if ( e.keyCode === 13 ) {
756
+ this.displayLayoutDirectory( $( e.currentTarget ).val(), 1, this.currentTab );
757
+ }
758
+ },
759
+
760
+ /**
761
+ * Attempt to set the 'Insert' button's state according to the `enabled` argument, also checking whether the
762
+ * requirements for inserting a layout have valid values.
763
+ */
764
+ updateButtonState: function ( enabled ) {
765
+ enabled = enabled && (
766
+ this.selectedLayoutItem || this.uploadedLayout
767
+ );
768
+ var $button = this.$( '.so-import-layout' );
769
+ $button.prop( "disabled", ! enabled );
770
+ if ( enabled ) {
771
+ $button.removeClass( 'disabled' );
772
+ } else {
773
+ $button.addClass( 'disabled' );
774
+ }
775
+ },
776
+
777
+ addLayoutToBuilder: function ( layout, position ) {
778
+ this.builder.addHistoryEntry( 'prebuilt_loaded' );
779
+ this.builder.model.loadPanelsData( layout, position );
780
+ this.addingLayout = false;
781
+ this.closeDialog();
782
+ }
783
+ } );
784
+
785
+ },{}],8:[function(require,module,exports){
786
+ var panels = window.panels, $ = jQuery;
787
+
788
+ module.exports = panels.view.dialog.extend({
789
+
790
+ cellPreviewTemplate: _.template( panels.helpers.utils.processTemplate( $('#siteorigin-panels-dialog-row-cell-preview').html() ) ),
791
+
792
+ editableLabel: true,
793
+
794
+ events: {
795
+ 'click .so-close': 'closeDialog',
796
+
797
+ // Toolbar buttons
798
+ 'click .so-toolbar .so-save': 'saveHandler',
799
+ 'click .so-toolbar .so-insert': 'insertHandler',
800
+ 'click .so-toolbar .so-delete': 'deleteHandler',
801
+ 'click .so-toolbar .so-duplicate': 'duplicateHandler',
802
+
803
+ // Changing the row
804
+ 'change .row-set-form > *': 'setCellsFromForm',
805
+ 'click .row-set-form button.set-row': 'setCellsFromForm',
806
+ },
807
+
808
+ dialogIcon: 'add-row',
809
+ dialogClass: 'so-panels-dialog-row-edit',
810
+ styleType: 'row',
811
+
812
+ dialogType: 'edit',
813
+
814
+ /**
815
+ * The current settings, not yet saved to the model
816
+ */
817
+ row: {
818
+ // This will be a clone of cells collection.
819
+ cells: null,
820
+ // The style settings of the row
821
+ style: {}
822
+ },
823
+
824
+ cellStylesCache: [],
825
+
826
+ initializeDialog: function () {
827
+ this.on('open_dialog', function () {
828
+ if (!_.isUndefined(this.model) && !_.isEmpty(this.model.get('cells'))) {
829
+ this.setRowModel(this.model);
830
+ } else {
831
+ this.setRowModel(null);
832
+ }
833
+
834
+ this.regenerateRowPreview();
835
+ }, this);
836
+
837
+ // This is the default row layout
838
+ this.row = {
839
+ cells: new panels.collection.cells([{weight: 0.5}, {weight: 0.5}]),
840
+ style: {}
841
+ };
842
+
843
+ // Refresh panels data after both dialog form components are loaded
844
+ this.dialogFormsLoaded = 0;
845
+ var thisView = this;
846
+ this.on('form_loaded styles_loaded', function () {
847
+ this.dialogFormsLoaded++;
848
+ if (this.dialogFormsLoaded === 2) {
849
+ thisView.updateModel({
850
+ refreshArgs: {
851
+ silent: true
852
+ }
853
+ });
854
+ }
855
+ });
856
+
857
+ this.on('close_dialog', this.closeHandler);
858
+
859
+ this.on( 'edit_label', function ( text ) {
860
+ // If text is set to default values, just clear it.
861
+ if ( text === panelsOptions.loc.row.add || text === panelsOptions.loc.row.edit ) {
862
+ text = '';
863
+ }
864
+ this.model.set( 'label', text );
865
+ if ( _.isEmpty( text ) ) {
866
+ var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
867
+ this.$( '.so-title').text( title );
868
+ }
869
+ }.bind( this ) );
870
+ },
871
+
872
+ /**
873
+ *
874
+ * @param dialogType Either "edit" or "create"
875
+ */
876
+ setRowDialogType: function (dialogType) {
877
+ this.dialogType = dialogType;
878
+ },
879
+
880
+ /**
881
+ * Render the new row dialog
882
+ */
883
+ render: function () {
884
+ var title = this.dialogType === 'create' ? panelsOptions.loc.row.add : panelsOptions.loc.row.edit;
885
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-row' ).html(), {
886
+ title: title,
887
+ dialogType: this.dialogType
888
+ } ) );
889
+
890
+ var titleElt = this.$( '.so-title' );
891
+
892
+ if ( this.model.has( 'label' ) && ! _.isEmpty( this.model.get( 'label' ) ) ) {
893
+ titleElt.text( this.model.get( 'label' ) );
894
+ }
895
+ this.$( '.so-edit-title' ).val( titleElt.text() );
896
+
897
+ // Now we need to attach the style window
898
+ this.styles = new panels.view.styles();
899
+ this.styles.model = this.model;
900
+ this.styles.render('row', this.builder.config.postId, {
901
+ builderType: this.builder.config.builderType,
902
+ dialog: this
903
+ });
904
+
905
+ if (!this.builder.supports('addRow')) {
906
+ this.$('.so-buttons .so-duplicate').remove();
907
+ }
908
+ if (!this.builder.supports('deleteRow')) {
909
+ this.$('.so-buttons .so-delete').remove();
910
+ }
911
+
912
+ var $rightSidebar = this.$('.so-sidebar.so-right-sidebar');
913
+ this.styles.attach($rightSidebar);
914
+
915
+ // Handle the loading class
916
+ this.styles.on('styles_loaded', function (hasStyles) {
917
+ // If we have styles remove the loading spinner, else remove the whole empty sidebar.
918
+ if (hasStyles) {
919
+ $rightSidebar.removeClass('so-panels-loading');
920
+ } else {
921
+ $rightSidebar.closest('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
922
+ $rightSidebar.remove();
923
+ }
924
+ }, this);
925
+ $rightSidebar.addClass('so-panels-loading');
926
+
927
+ if (!_.isUndefined(this.model)) {
928
+ // Set the initial value of the
929
+ this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
930
+ if ( this.model.has( 'ratio' ) ) {
931
+ this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
932
+ }
933
+ if ( this.model.has( 'ratio_direction' ) ) {
934
+ this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
935
+ }
936
+ }
937
+
938
+ this.$('input.so-row-field').keyup(function () {
939
+ $(this).trigger('change');
940
+ });
941
+
942
+ return this;
943
+ },
944
+
945
+ /**
946
+ * Set the row model we'll be using for this dialog.
947
+ *
948
+ * @param model
949
+ */
950
+ setRowModel: function (model) {
951
+ this.model = model;
952
+
953
+ if (_.isEmpty(this.model)) {
954
+ return this;
955
+ }
956
+
957
+ // Set the rows to be a copy of the model
958
+ this.row = {
959
+ cells: this.model.get('cells').clone(),
960
+ style: {},
961
+ ratio: this.model.get('ratio'),
962
+ ratio_direction: this.model.get('ratio_direction'),
963
+ };
964
+
965
+ // Set the initial value of the cell field.
966
+ this.$( 'input[name="cells"].so-row-field' ).val( this.model.get( 'cells' ).length );
967
+ if ( this.model.has( 'ratio' ) ) {
968
+ this.$( 'select[name="ratio"].so-row-field' ).val( this.model.get( 'ratio' ) );
969
+ }
970
+ if ( this.model.has( 'ratio_direction' ) ) {
971
+ this.$( 'select[name="ratio_direction"].so-row-field' ).val( this.model.get( 'ratio_direction' ) );
972
+ }
973
+
974
+ this.clearCellStylesCache();
975
+
976
+ return this;
977
+ },
978
+
979
+ /**
980
+ * Regenerate the row preview and resizing interface.
981
+ */
982
+ regenerateRowPreview: function () {
983
+ var thisDialog = this;
984
+ var rowPreview = this.$('.row-preview');
985
+
986
+ // If no selected cell, select the first cell.
987
+ var selectedIndex = this.getSelectedCellIndex();
988
+
989
+ rowPreview.empty();
990
+
991
+ var timeout;
992
+
993
+ // Represent the cells
994
+ this.row.cells.each(function (cellModel, i) {
995
+ var newCell = $(this.cellPreviewTemplate({weight: cellModel.get('weight')}));
996
+ rowPreview.append(newCell);
997
+
998
+ if(i == selectedIndex) {
999
+ newCell.find('.preview-cell-in').addClass('cell-selected');
1000
+ }
1001
+
1002
+ var prevCell = newCell.prev();
1003
+ var handle;
1004
+
1005
+ if (prevCell.length) {
1006
+ handle = $('<div class="resize-handle"></div>');
1007
+ handle
1008
+ .appendTo(newCell)
1009
+ .dblclick(function () {
1010
+ var prevCellModel = thisDialog.row.cells.at(i - 1);
1011
+ var t = cellModel.get('weight') + prevCellModel.get('weight');
1012
+ cellModel.set('weight', t / 2);
1013
+ prevCellModel.set('weight', t / 2);
1014
+ thisDialog.scaleRowWidths();
1015
+ });
1016
+
1017
+ handle.draggable({
1018
+ axis: 'x',
1019
+ containment: rowPreview,
1020
+ start: function (e, ui) {
1021
+
1022
+ // Create the clone for the current cell
1023
+ var newCellClone = newCell.clone().appendTo(ui.helper).css({
1024
+ position: 'absolute',
1025
+ top: '0',
1026
+ width: newCell.outerWidth(),
1027
+ left: 6,
1028
+ height: newCell.outerHeight()
1029
+ });
1030
+ newCellClone.find('.resize-handle').remove();
1031
+
1032
+ // Create the clone for the previous cell
1033
+ var prevCellClone = prevCell.clone().appendTo(ui.helper).css({
1034
+ position: 'absolute',
1035
+ top: '0',
1036
+ width: prevCell.outerWidth(),
1037
+ right: 6,
1038
+ height: prevCell.outerHeight()
1039
+ });
1040
+ prevCellClone.find('.resize-handle').remove();
1041
+
1042
+ $(this).data({
1043
+ 'newCellClone': newCellClone,
1044
+ 'prevCellClone': prevCellClone
1045
+ });
1046
+
1047
+ // Hide the
1048
+ newCell.find('> .preview-cell-in').css('visibility', 'hidden');
1049
+ prevCell.find('> .preview-cell-in').css('visibility', 'hidden');
1050
+ },
1051
+ drag: function (e, ui) {
1052
+ // Calculate the new cell and previous cell widths as a percent
1053
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1054
+ var prevCellWeight = thisDialog.row.cells.at(i - 1).get('weight');
1055
+ var ncw = cellWeight - (
1056
+ (
1057
+ ui.position.left + 6
1058
+ ) / rowPreview.width()
1059
+ );
1060
+ var pcw = prevCellWeight + (
1061
+ (
1062
+ ui.position.left + 6
1063
+ ) / rowPreview.width()
1064
+ );
1065
+
1066
+ var helperLeft = ui.helper.offset().left - rowPreview.offset().left - 6;
1067
+
1068
+ $(this).data('newCellClone').css('width', rowPreview.width() * ncw)
1069
+ .find('.preview-cell-weight').html(Math.round(ncw * 1000) / 10);
1070
+
1071
+ $(this).data('prevCellClone').css('width', rowPreview.width() * pcw)
1072
+ .find('.preview-cell-weight').html(Math.round(pcw * 1000) / 10);
1073
+ },
1074
+ stop: function (e, ui) {
1075
+ // Remove the clones
1076
+ $(this).data('newCellClone').remove();
1077
+ $(this).data('prevCellClone').remove();
1078
+
1079
+ // Reshow the main cells
1080
+ newCell.find('.preview-cell-in').css('visibility', 'visible');
1081
+ prevCell.find('.preview-cell-in').css('visibility', 'visible');
1082
+
1083
+ // Calculate the new cell weights
1084
+ var offset = ui.position.left + 6;
1085
+ var percent = offset / rowPreview.width();
1086
+
1087
+ // Ignore this if any of the cells are below 2% in width.
1088
+ var cellModel = thisDialog.row.cells.at(i);
1089
+ var prevCellModel = thisDialog.row.cells.at(i - 1);
1090
+ if (cellModel.get('weight') - percent > 0.02 && prevCellModel.get('weight') + percent > 0.02) {
1091
+ cellModel.set('weight', cellModel.get('weight') - percent);
1092
+ prevCellModel.set('weight', prevCellModel.get('weight') + percent);
1093
+ }
1094
+
1095
+ thisDialog.scaleRowWidths();
1096
+ ui.helper.css('left', -6);
1097
+ }
1098
+ });
1099
+ }
1100
+
1101
+ newCell.click(function (event) {
1102
+
1103
+ if ( ! ( $(event.target).is('.preview-cell') || $(event.target).is('.preview-cell-in') ) ) {
1104
+ return;
1105
+ }
1106
+
1107
+ var cell = $(event.target);
1108
+ cell.closest('.row-preview').find('.preview-cell .preview-cell-in').removeClass('cell-selected');
1109
+ cell.addClass('cell-selected');
1110
+
1111
+ this.openSelectedCellStyles();
1112
+
1113
+ }.bind(this));
1114
+
1115
+ // Make this row weight click editable
1116
+ newCell.find('.preview-cell-weight').click(function (ci) {
1117
+
1118
+ // Disable the draggable while entering values
1119
+ thisDialog.$('.resize-handle').css('pointer-event', 'none').draggable('disable');
1120
+
1121
+ rowPreview.find('.preview-cell-weight').each(function () {
1122
+ var $$ = jQuery(this).hide();
1123
+ $('<input type="text" class="preview-cell-weight-input no-user-interacted" />')
1124
+ .val(parseFloat($$.html())).insertAfter($$)
1125
+ .focus(function () {
1126
+ clearTimeout(timeout);
1127
+ })
1128
+ .keyup(function (e) {
1129
+ if (e.keyCode !== 9) {
1130
+ // Only register the interaction if the user didn't press tab
1131
+ $(this).removeClass('no-user-interacted');
1132
+ }
1133
+
1134
+ // Enter is clicked
1135
+ if (e.keyCode === 13) {
1136
+ e.preventDefault();
1137
+ $(this).blur();
1138
+ }
1139
+ })
1140
+ .keydown(function (e) {
1141
+ if (e.keyCode === 9) {
1142
+ e.preventDefault();
1143
+
1144
+ // Tab will always cycle around the row inputs
1145
+ var inputs = rowPreview.find('.preview-cell-weight-input');
1146
+ var i = inputs.index($(this));
1147
+ if (i === inputs.length - 1) {
1148
+ inputs.eq(0).focus().select();
1149
+ } else {
1150
+ inputs.eq(i + 1).focus().select();
1151
+ }
1152
+ }
1153
+ })
1154
+ .blur(function () {
1155
+ rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1156
+ if (isNaN(parseFloat($(el).val()))) {
1157
+ $(el).val(Math.floor(thisDialog.row.cells.at(i).get('weight') * 1000) / 10);
1158
+ }
1159
+ });
1160
+
1161
+ timeout = setTimeout(function () {
1162
+ // If there are no weight inputs, then skip this
1163
+ if (rowPreview.find('.preview-cell-weight-input').length === 0) {
1164
+ return false;
1165
+ }
1166
+
1167
+ // Go through all the inputs
1168
+ var rowWeights = [],
1169
+ rowChanged = [],
1170
+ changedSum = 0,
1171
+ unchangedSum = 0;
1172
+
1173
+ rowPreview.find('.preview-cell-weight-input').each(function (i, el) {
1174
+ var val = parseFloat($(el).val());
1175
+ if (isNaN(val)) {
1176
+ val = 1 / thisDialog.row.cells.length;
1177
+ } else {
1178
+ val = Math.round(val * 10) / 1000;
1179
+ }
1180
+
1181
+ // Check within 3 decimal points
1182
+ var changed = !$(el).hasClass('no-user-interacted');
1183
+
1184
+ rowWeights.push(val);
1185
+ rowChanged.push(changed);
1186
+
1187
+ if (changed) {
1188
+ changedSum += val;
1189
+ } else {
1190
+ unchangedSum += val;
1191
+ }
1192
+ });
1193
+
1194
+ if (changedSum > 0 && unchangedSum > 0 && (
1195
+ 1 - changedSum
1196
+ ) > 0) {
1197
+ // Balance out the unchanged rows to occupy the weight left over by the changed sum
1198
+ for (var i = 0; i < rowWeights.length; i++) {
1199
+ if (!rowChanged[i]) {
1200
+ rowWeights[i] = (
1201
+ rowWeights[i] / unchangedSum
1202
+ ) * (
1203
+ 1 - changedSum
1204
+ );
1205
+ }
1206
+ }
1207
+ }
1208
+
1209
+ // Last check to ensure total weight is 1
1210
+ var sum = _.reduce(rowWeights, function (memo, num) {
1211
+ return memo + num;
1212
+ });
1213
+ rowWeights = rowWeights.map(function (w) {
1214
+ return w / sum;
1215
+ });
1216
+
1217
+ // Set the new cell weights and regenerate the preview.
1218
+ if (Math.min.apply(Math, rowWeights) > 0.01) {
1219
+ thisDialog.row.cells.each(function (cell, i) {
1220
+ cell.set('weight', rowWeights[i]);
1221
+ });
1222
+ }
1223
+
1224
+ // Now lets animate the cells into their new widths
1225
+ rowPreview.find('.preview-cell').each(function (i, el) {
1226
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1227
+ $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1228
+ $(el).find('.preview-cell-weight-input').val(Math.round(cellWeight * 1000) / 10);
1229
+ });
1230
+
1231
+ // So the draggable handle is not hidden.
1232
+ rowPreview.find('.preview-cell').css('overflow', 'visible');
1233
+
1234
+ setTimeout(function () {
1235
+ thisDialog.regenerateRowPreview();
1236
+ }, 260);
1237
+
1238
+ }, 100);
1239
+ })
1240
+ .click(function () {
1241
+ $(this).select();
1242
+ });
1243
+ });
1244
+
1245
+ $(this).siblings('.preview-cell-weight-input').select();
1246
+
1247
+ });
1248
+
1249
+ }, this);
1250
+
1251
+ this.openSelectedCellStyles();
1252
+
1253
+ this.trigger('form_loaded', this);
1254
+ },
1255
+
1256
+ getSelectedCellIndex: function() {
1257
+ var selectedIndex = -1;
1258
+ this.$('.preview-cell .preview-cell-in').each(function(index, el) {
1259
+ if($(el).is('.cell-selected')) {
1260
+ selectedIndex = index;
1261
+ }
1262
+ });
1263
+ return selectedIndex;
1264
+ },
1265
+
1266
+ openSelectedCellStyles: function() {
1267
+ if (!_.isUndefined(this.cellStyles)) {
1268
+ if (this.cellStyles.stylesLoaded) {
1269
+ var style = {};
1270
+ try {
1271
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1272
+ }
1273
+ catch (err) {
1274
+ console.log('Error retrieving cell styles - ' + err.message);
1275
+ }
1276
+
1277
+ this.cellStyles.model.set('style', style);
1278
+ }
1279
+ this.cellStyles.detach();
1280
+ }
1281
+
1282
+ this.cellStyles = this.getSelectedCellStyles();
1283
+
1284
+ if ( this.cellStyles ) {
1285
+ var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1286
+ this.cellStyles.attach( $rightSidebar );
1287
+
1288
+ if ( !this.cellStyles.stylesLoaded ) {
1289
+ this.cellStyles.on( 'styles_loaded', function () {
1290
+ $rightSidebar.removeClass( 'so-panels-loading' );
1291
+ }, this );
1292
+ $rightSidebar.addClass( 'so-panels-loading' );
1293
+ }
1294
+ }
1295
+ },
1296
+
1297
+ getSelectedCellStyles: function () {
1298
+ var cellIndex = this.getSelectedCellIndex();
1299
+ if ( cellIndex > -1 ) {
1300
+ var cellStyles = this.cellStylesCache[cellIndex];
1301
+ if ( !cellStyles ) {
1302
+ cellStyles = new panels.view.styles();
1303
+ cellStyles.model = this.row.cells.at( cellIndex );
1304
+ cellStyles.render( 'cell', this.builder.config.postId, {
1305
+ builderType: this.builder.config.builderType,
1306
+ dialog: this,
1307
+ index: cellIndex,
1308
+ } );
1309
+ this.cellStylesCache[cellIndex] = cellStyles;
1310
+ }
1311
+ }
1312
+
1313
+ return cellStyles;
1314
+ },
1315
+
1316
+ clearCellStylesCache: function () {
1317
+ // Call remove() on all cell styles to remove data, event listeners etc.
1318
+ this.cellStylesCache.forEach(function (cellStyles) {
1319
+ cellStyles.remove();
1320
+ });
1321
+ this.cellStylesCache = [];
1322
+ },
1323
+
1324
+ /**
1325
+ * Visually scale the row widths based on the cell weights
1326
+ */
1327
+ scaleRowWidths: function () {
1328
+ var thisDialog = this;
1329
+ this.$('.row-preview .preview-cell').each(function (i, el) {
1330
+ var cell = thisDialog.row.cells.at(i);
1331
+ $(el)
1332
+ .css('width', cell.get('weight') * 100 + "%")
1333
+ .find('.preview-cell-weight').html(Math.round(cell.get('weight') * 1000) / 10);
1334
+ });
1335
+ },
1336
+
1337
+ /**
1338
+ * Get the weights from the
1339
+ */
1340
+ setCellsFromForm: function () {
1341
+
1342
+ try {
1343
+ var f = {
1344
+ 'cells': parseInt(this.$('.row-set-form input[name="cells"]').val()),
1345
+ 'ratio': parseFloat(this.$('.row-set-form select[name="ratio"]').val()),
1346
+ 'direction': this.$('.row-set-form select[name="ratio_direction"]').val()
1347
+ };
1348
+
1349
+ if (_.isNaN(f.cells)) {
1350
+ f.cells = 1;
1351
+ }
1352
+ if (isNaN(f.ratio)) {
1353
+ f.ratio = 1;
1354
+ }
1355
+ if (f.cells < 1) {
1356
+ f.cells = 1;
1357
+ this.$('.row-set-form input[name="cells"]').val(f.cells);
1358
+ }
1359
+ else if (f.cells > 12) {
1360
+ f.cells = 12;
1361
+ this.$('.row-set-form input[name="cells"]').val(f.cells);
1362
+ }
1363
+
1364
+ this.$('.row-set-form select[name="ratio"]').val(f.ratio);
1365
+
1366
+ var cells = [];
1367
+ var cellCountChanged = (
1368
+ this.row.cells.length !== f.cells
1369
+ );
1370
+
1371
+ // Now, lets create some cells
1372
+ var currentWeight = 1;
1373
+ for (var i = 0; i < f.cells; i++) {
1374
+ cells.push(currentWeight);
1375
+ currentWeight *= f.ratio;
1376
+ }
1377
+
1378
+ // Now lets make sure that the row weights add up to 1
1379
+
1380
+ var totalRowWeight = _.reduce(cells, function (memo, weight) {
1381
+ return memo + weight;
1382
+ });
1383
+ cells = _.map(cells, function (cell) {
1384
+ return cell / totalRowWeight;
1385
+ });
1386
+
1387
+ // Don't return cells that are too small
1388
+ cells = _.filter(cells, function (cell) {
1389
+ return cell > 0.01;
1390
+ });
1391
+
1392
+ if (f.direction === 'left') {
1393
+ cells = cells.reverse();
1394
+ }
1395
+
1396
+ // Discard deleted cells.
1397
+ this.row.cells = new panels.collection.cells(this.row.cells.first(cells.length));
1398
+
1399
+ _.each(cells, function (cellWeight, index) {
1400
+ var cell = this.row.cells.at(index);
1401
+ if (!cell) {
1402
+ cell = new panels.model.cell({weight: cellWeight, row: this.model});
1403
+ this.row.cells.add(cell);
1404
+ } else {
1405
+ cell.set('weight', cellWeight);
1406
+ }
1407
+ }.bind(this));
1408
+
1409
+ this.row.ratio = f.ratio;
1410
+ this.row.ratio_direction = f.direction;
1411
+
1412
+ if (cellCountChanged) {
1413
+ this.regenerateRowPreview();
1414
+ } else {
1415
+ var thisDialog = this;
1416
+
1417
+ // Now lets animate the cells into their new widths
1418
+ this.$('.preview-cell').each(function (i, el) {
1419
+ var cellWeight = thisDialog.row.cells.at(i).get('weight');
1420
+ $(el).animate({'width': Math.round(cellWeight * 1000) / 10 + "%"}, 250);
1421
+ $(el).find('.preview-cell-weight').html(Math.round(cellWeight * 1000) / 10);
1422
+ });
1423
+
1424
+ // So the draggable handle is not hidden.
1425
+ this.$('.preview-cell').css('overflow', 'visible');
1426
+
1427
+ setTimeout(function () {
1428
+ thisDialog.regenerateRowPreview();
1429
+ }, 260);
1430
+ }
1431
+ }
1432
+ catch (err) {
1433
+ console.log('Error setting cells - ' + err.message);
1434
+ }
1435
+
1436
+
1437
+ // Remove the button primary class
1438
+ this.$('.row-set-form .so-button-row-set').removeClass('button-primary');
1439
+ },
1440
+
1441
+ /**
1442
+ * Handle a click on the dialog left bar tab
1443
+ */
1444
+ tabClickHandler: function ($t) {
1445
+ if ($t.attr('href') === '#row-layout') {
1446
+ this.$('.so-panels-dialog').addClass('so-panels-dialog-has-right-sidebar');
1447
+ } else {
1448
+ this.$('.so-panels-dialog').removeClass('so-panels-dialog-has-right-sidebar');
1449
+ }
1450
+ },
1451
+
1452
+ /**
1453
+ * Update the current model with what we have in the dialog
1454
+ */
1455
+ updateModel: function (args) {
1456
+ args = _.extend({
1457
+ refresh: true,
1458
+ refreshArgs: null
1459
+ }, args);
1460
+
1461
+ // Set the cells
1462
+ if (!_.isEmpty(this.model)) {
1463
+ this.model.setCells( this.row.cells );
1464
+ this.model.set( 'ratio', this.row.ratio );
1465
+ this.model.set( 'ratio_direction', this.row.ratio_direction );
1466
+ }
1467
+
1468
+ // Update the row styles if they've loaded
1469
+ if (!_.isUndefined(this.styles) && this.styles.stylesLoaded) {
1470
+ // This is an edit dialog, so there are styles
1471
+ var style = {};
1472
+ try {
1473
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-row-styles').style;
1474
+ }
1475
+ catch (err) {
1476
+ console.log('Error retrieving row styles - ' + err.message);
1477
+ }
1478
+
1479
+ this.model.set('style', style);
1480
+ }
1481
+
1482
+ // Update the cell styles if any are showing.
1483
+ if (!_.isUndefined(this.cellStyles) && this.cellStyles.stylesLoaded) {
1484
+
1485
+ var style = {};
1486
+ try {
1487
+ style = this.getFormValues('.so-sidebar .so-visual-styles.so-cell-styles').style;
1488
+ }
1489
+ catch (err) {
1490
+ console.log('Error retrieving cell styles - ' + err.message);
1491
+ }
1492
+
1493
+ this.cellStyles.model.set('style', style);
1494
+ }
1495
+
1496
+ if (args.refresh) {
1497
+ this.builder.model.refreshPanelsData(args.refreshArgs);
1498
+ }
1499
+ },
1500
+
1501
+ /**
1502
+ * Insert the new row
1503
+ */
1504
+ insertHandler: function () {
1505
+ this.builder.addHistoryEntry('row_added');
1506
+
1507
+ this.updateModel();
1508
+
1509
+ var activeCell = this.builder.getActiveCell({
1510
+ createCell: false,
1511
+ });
1512
+
1513
+ var options = {};
1514
+ if (activeCell !== null) {
1515
+ options.at = this.builder.model.get('rows').indexOf(activeCell.row) + 1;
1516
+ }
1517
+
1518
+ // Set up the model and add it to the builder
1519
+ this.model.collection = this.builder.model.get('rows');
1520
+ this.builder.model.get('rows').add(this.model, options);
1521
+
1522
+ this.closeDialog();
1523
+
1524
+ this.builder.model.refreshPanelsData();
1525
+
1526
+ return false;
1527
+ },
1528
+
1529
+ /**
1530
+ * We'll just save this model and close the dialog
1531
+ */
1532
+ saveHandler: function () {
1533
+ this.builder.addHistoryEntry('row_edited');
1534
+ this.updateModel();
1535
+ this.closeDialog();
1536
+
1537
+ this.builder.model.refreshPanelsData();
1538
+
1539
+ return false;
1540
+ },
1541
+
1542
+ /**
1543
+ * The user clicks delete, so trigger deletion on the row model
1544
+ */
1545
+ deleteHandler: function () {
1546
+ // Trigger a destroy on the model that will happen with a visual indication to the user
1547
+ this.model.trigger('visual_destroy');
1548
+ this.closeDialog({silent: true});
1549
+
1550
+ return false;
1551
+ },
1552
+
1553
+ /**
1554
+ * Duplicate this row
1555
+ */
1556
+ duplicateHandler: function () {
1557
+ this.builder.addHistoryEntry('row_duplicated');
1558
+
1559
+ var duplicateRow = this.model.clone(this.builder.model);
1560
+
1561
+ this.builder.model.get('rows').add( duplicateRow, {
1562
+ at: this.builder.model.get('rows').indexOf(this.model) + 1
1563
+ } );
1564
+
1565
+ this.closeDialog({silent: true});
1566
+
1567
+ return false;
1568
+ },
1569
+
1570
+ closeHandler: function() {
1571
+ this.clearCellStylesCache();
1572
+ if( ! _.isUndefined(this.cellStyles) ) {
1573
+ this.cellStyles = undefined;
1574
+ }
1575
+ },
1576
+
1577
+ });
1578
+
1579
+ },{}],9:[function(require,module,exports){
1580
+ var panels = window.panels, $ = jQuery;
1581
+ var jsWidget = require( '../view/widgets/js-widget' );
1582
+
1583
+ module.exports = panels.view.dialog.extend( {
1584
+
1585
+ builder: null,
1586
+ sidebarWidgetTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-widget-sidebar-widget' ).html() ) ),
1587
+
1588
+ dialogClass: 'so-panels-dialog-edit-widget',
1589
+ dialogIcon: 'add-widget',
1590
+
1591
+ widgetView: false,
1592
+ savingWidget: false,
1593
+ editableLabel: true,
1594
+
1595
+ events: {
1596
+ 'click .so-close': 'saveHandler',
1597
+ 'click .so-nav.so-previous': 'navToPrevious',
1598
+ 'click .so-nav.so-next': 'navToNext',
1599
+
1600
+ // Action handlers
1601
+ 'click .so-toolbar .so-delete': 'deleteHandler',
1602
+ 'click .so-toolbar .so-duplicate': 'duplicateHandler'
1603
+ },
1604
+
1605
+ initializeDialog: function () {
1606
+ var thisView = this;
1607
+ this.model.on( 'change:values', this.handleChangeValues, this );
1608
+ this.model.on( 'destroy', this.remove, this );
1609
+
1610
+ // Refresh panels data after both dialog form components are loaded
1611
+ this.dialogFormsLoaded = 0;
1612
+ this.on( 'form_loaded styles_loaded', function () {
1613
+ this.dialogFormsLoaded ++;
1614
+ if ( this.dialogFormsLoaded === 2 ) {
1615
+ thisView.updateModel( {
1616
+ refreshArgs: {
1617
+ silent: true
1618
+ }
1619
+ } );
1620
+ }
1621
+ } );
1622
+
1623
+ this.on( 'edit_label', function ( text ) {
1624
+ // If text is set to default value, just clear it.
1625
+ if ( text === panelsOptions.widgets[ this.model.get( 'class' ) ][ 'title' ] ) {
1626
+ text = '';
1627
+ }
1628
+ this.model.set( 'label', text );
1629
+ if ( _.isEmpty( text ) ) {
1630
+ this.$( '.so-title' ).text( this.model.getWidgetField( 'title' ) );
1631
+ }
1632
+ }.bind( this ) );
1633
+ },
1634
+
1635
+ /**
1636
+ * Render the widget dialog.
1637
+ */
1638
+ render: function () {
1639
+ // Render the dialog and attach it to the builder interface
1640
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widget' ).html(), {} ) );
1641
+ this.loadForm();
1642
+
1643
+ var title = this.model.getWidgetField( 'title' );
1644
+ this.$( '.so-title .widget-name' ).html( title );
1645
+ this.$( '.so-edit-title' ).val( title );
1646
+
1647
+ if( ! this.builder.supports( 'addWidget' ) ) {
1648
+ this.$( '.so-buttons .so-duplicate' ).remove();
1649
+ }
1650
+ if( ! this.builder.supports( 'deleteWidget' ) ) {
1651
+ this.$( '.so-buttons .so-delete' ).remove();
1652
+ }
1653
+
1654
+ // Now we need to attach the style window
1655
+ this.styles = new panels.view.styles();
1656
+ this.styles.model = this.model;
1657
+ this.styles.render( 'widget', this.builder.config.postId, {
1658
+ builderType: this.builder.config.builderType,
1659
+ dialog: this
1660
+ } );
1661
+
1662
+ var $rightSidebar = this.$( '.so-sidebar.so-right-sidebar' );
1663
+ this.styles.attach( $rightSidebar );
1664
+
1665
+ // Handle the loading class
1666
+ this.styles.on( 'styles_loaded', function ( hasStyles ) {
1667
+ // If we have styles remove the loading spinner, else remove the whole empty sidebar.
1668
+ if ( hasStyles ) {
1669
+ $rightSidebar.removeClass( 'so-panels-loading' );
1670
+ } else {
1671
+ $rightSidebar.closest( '.so-panels-dialog' ).removeClass( 'so-panels-dialog-has-right-sidebar' );
1672
+ $rightSidebar.remove();
1673
+ }
1674
+ }, this );
1675
+ $rightSidebar.addClass( 'so-panels-loading' );
1676
+ },
1677
+
1678
+ /**
1679
+ * Get the previous widget editing dialog by looking at the dom.
1680
+ * @returns {*}
1681
+ */
1682
+ getPrevDialog: function () {
1683
+ var widgets = this.builder.$( '.so-cells .cell .so-widget' );
1684
+ if ( widgets.length <= 1 ) {
1685
+ return false;
1686
+ }
1687
+ var currentIndex = widgets.index( this.widgetView.$el );
1688
+
1689
+ if ( currentIndex === 0 ) {
1690
+ return false;
1691
+ } else {
1692
+ do {
1693
+ widgetView = widgets.eq( --currentIndex ).data( 'view' );
1694
+ if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
1695
+ return widgetView.getEditDialog();
1696
+ }
1697
+ } while( ! _.isUndefined( widgetView ) && currentIndex > 0 );
1698
+ }
1699
+
1700
+ return false;
1701
+ },
1702
+
1703
+ /**
1704
+ * Get the next widget editing dialog by looking at the dom.
1705
+ * @returns {*}
1706
+ */
1707
+ getNextDialog: function () {
1708
+ var widgets = this.builder.$( '.so-cells .cell .so-widget' );
1709
+ if ( widgets.length <= 1 ) {
1710
+ return false;
1711
+ }
1712
+
1713
+ var currentIndex = widgets.index( this.widgetView.$el ), widgetView;
1714
+
1715
+ if ( currentIndex === widgets.length - 1 ) {
1716
+ return false;
1717
+ } else {
1718
+ do {
1719
+ widgetView = widgets.eq( ++currentIndex ).data( 'view' );
1720
+ if ( ! _.isUndefined( widgetView ) && ! widgetView.model.get( 'read_only' ) ) {
1721
+ return widgetView.getEditDialog();
1722
+ }
1723
+ } while( ! _.isUndefined( widgetView ) );
1724
+ }
1725
+
1726
+ return false;
1727
+ },
1728
+
1729
+ /**
1730
+ * Load the widget form from the server.
1731
+ * This is called when rendering the dialog for the first time.
1732
+ */
1733
+ loadForm: function () {
1734
+ // don't load the form if this dialog hasn't been rendered yet
1735
+ if ( ! this.$( '> *' ).length ) {
1736
+ return;
1737
+ }
1738
+
1739
+ this.$( '.so-content' ).addClass( 'so-panels-loading' );
1740
+
1741
+ var data = {
1742
+ 'action': 'so_panels_widget_form',
1743
+ 'widget': this.model.get( 'class' ),
1744
+ 'instance': JSON.stringify( this.model.get( 'values' ) ),
1745
+ 'raw': this.model.get( 'raw' )
1746
+ };
1747
+
1748
+ $.post(
1749
+ panelsOptions.ajaxurl,
1750
+ data,
1751
+ function ( result ) {
1752
+ // Add in the CID of the widget model
1753
+ var html = result.replace( /{\$id}/g, this.model.cid );
1754
+
1755
+ // Load this content into the form
1756
+ var $soContent = this.$( '.so-content' );
1757
+ $soContent
1758
+ .removeClass( 'so-panels-loading' )
1759
+ .html( html );
1760
+
1761
+ // Trigger all the necessary events
1762
+ this.trigger( 'form_loaded', this );
1763
+
1764
+ // For legacy compatibility, trigger a panelsopen event
1765
+ this.$( '.panel-dialog' ).trigger( 'panelsopen' );
1766
+
1767
+ // If the main dialog is closed from this point on, save the widget content
1768
+ this.on( 'close_dialog', this.updateModel, this );
1769
+
1770
+ var widgetContent = $soContent.find( '> .widget-content' );
1771
+ // If there's a widget content wrapper, this is one of the new widgets in WP 4.8 which need some special
1772
+ // handling in JS.
1773
+ if ( widgetContent.length > 0 ) {
1774
+ jsWidget.addWidget( $soContent, this.model.widget_id );
1775
+ }
1776
+
1777
+ }.bind( this ),
1778
+ 'html'
1779
+ );
1780
+ },
1781
+
1782
+ /**
1783
+ * Save the widget from the form to the model
1784
+ */
1785
+ updateModel: function ( args ) {
1786
+ args = _.extend( {
1787
+ refresh: true,
1788
+ refreshArgs: null
1789
+ }, args );
1790
+
1791
+ // Get the values from the form and assign the new values to the model
1792
+ this.savingWidget = true;
1793
+
1794
+ if ( ! this.model.get( 'missing' ) ) {
1795
+ // Only get the values for non missing widgets.
1796
+ var values = this.getFormValues();
1797
+ if ( _.isUndefined( values.widgets ) ) {
1798
+ values = {};
1799
+ } else {
1800
+ values = values.widgets;
1801
+ values = values[Object.keys( values )[0]];
1802
+ }
1803
+
1804
+ this.model.setValues( values );
1805
+ this.model.set( 'raw', true ); // We've saved from the widget form, so this is now raw
1806
+ }
1807
+
1808
+ if ( this.styles.stylesLoaded ) {
1809
+ // If the styles view has loaded
1810
+ var style = {};
1811
+ try {
1812
+ style = this.getFormValues( '.so-sidebar .so-visual-styles' ).style;
1813
+ }
1814
+ catch ( e ) {
1815
+ }
1816
+ this.model.set( 'style', style );
1817
+ }
1818
+
1819
+ this.savingWidget = false;
1820
+
1821
+ if ( args.refresh ) {
1822
+ this.builder.model.refreshPanelsData( args.refreshArgs );
1823
+ }
1824
+ },
1825
+
1826
+ /**
1827
+ *
1828
+ */
1829
+ handleChangeValues: function () {
1830
+ if ( ! this.savingWidget ) {
1831
+ // Reload the form when we've changed the model and we're not currently saving from the form
1832
+ this.loadForm();
1833
+ }
1834
+ },
1835
+
1836
+ /**
1837
+ * Save a history entry for this widget. Called when the dialog is closed.
1838
+ */
1839
+ saveHandler: function () {
1840
+ this.builder.addHistoryEntry( 'widget_edited' );
1841
+ this.closeDialog();
1842
+ },
1843
+
1844
+ /**
1845
+ * When the user clicks delete.
1846
+ *
1847
+ * @returns {boolean}
1848
+ */
1849
+ deleteHandler: function () {
1850
+
1851
+ this.model.trigger( 'visual_destroy' );
1852
+ this.closeDialog( {silent: true} );
1853
+ this.builder.model.refreshPanelsData();
1854
+
1855
+ return false;
1856
+ },
1857
+
1858
+ duplicateHandler: function () {
1859
+ this.model.trigger( 'user_duplicate' );
1860
+
1861
+ this.closeDialog( {silent: true} );
1862
+ this.builder.model.refreshPanelsData();
1863
+
1864
+ return false;
1865
+ }
1866
+
1867
+ } );
1868
+
1869
+ },{"../view/widgets/js-widget":31}],10:[function(require,module,exports){
1870
+ var panels = window.panels, $ = jQuery;
1871
+
1872
+ module.exports = panels.view.dialog.extend( {
1873
+
1874
+ builder: null,
1875
+ widgetTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-dialog-widgets-widget' ).html() ) ),
1876
+ filter: {},
1877
+
1878
+ dialogClass: 'so-panels-dialog-add-widget',
1879
+ dialogIcon: 'add-widget',
1880
+
1881
+ events: {
1882
+ 'click .so-close': 'closeDialog',
1883
+ 'click .widget-type': 'widgetClickHandler',
1884
+ 'keyup .so-sidebar-search': 'searchHandler'
1885
+ },
1886
+
1887
+ /**
1888
+ * Initialize the widget adding dialog
1889
+ */
1890
+ initializeDialog: function () {
1891
+
1892
+ this.on( 'open_dialog', function () {
1893
+ this.filter.search = '';
1894
+ this.filterWidgets( this.filter );
1895
+ }, this );
1896
+
1897
+ this.on( 'open_dialog_complete', function () {
1898
+ // Clear the search and re-filter the widgets when we open the dialog
1899
+ this.$( '.so-sidebar-search' ).val( '' ).focus();
1900
+ this.balanceWidgetHeights();
1901
+ } );
1902
+
1903
+ // We'll implement a custom tab click handler
1904
+ this.on( 'tab_click', this.tabClickHandler, this );
1905
+ },
1906
+
1907
+ render: function () {
1908
+ // Render the dialog and attach it to the builder interface
1909
+ this.renderDialog( this.parseDialogContent( $( '#siteorigin-panels-dialog-widgets' ).html(), {} ) );
1910
+
1911
+ // Add all the widgets
1912
+ _.each( panelsOptions.widgets, function ( widget ) {
1913
+ var $w = $( this.widgetTemplate( {
1914
+ title: widget.title,
1915
+ description: widget.description
1916
+ } ) );
1917
+
1918
+ if ( _.isUndefined( widget.icon ) ) {
1919
+ widget.icon = 'dashicons dashicons-admin-generic';
1920
+ }
1921
+
1922
+ $( '<span class="widget-icon" />' ).addClass( widget.icon ).prependTo( $w.find( '.widget-type-wrapper' ) );
1923
+
1924
+ $w.data( 'class', widget.class ).appendTo( this.$( '.widget-type-list' ) );
1925
+ }, this );
1926
+
1927
+ // Add the sidebar tabs
1928
+ var tabs = this.$( '.so-sidebar-tabs' );
1929
+ _.each( panelsOptions.widget_dialog_tabs, function ( tab ) {
1930
+ $( this.dialogTabTemplate( {'title': tab.title} ) ).data( {
1931
+ 'message': tab.message,
1932
+ 'filter': tab.filter
1933
+ } ).appendTo( tabs );
1934
+ }, this );
1935
+
1936
+ // We'll be using tabs, so initialize them
1937
+ this.initTabs();
1938
+
1939
+ var thisDialog = this;
1940
+ $( window ).resize( function () {
1941
+ thisDialog.balanceWidgetHeights();
1942
+ } );
1943
+ },
1944
+
1945
+ /**
1946
+ * Handle a tab being clicked
1947
+ */
1948
+ tabClickHandler: function ( $t ) {
1949
+ // Get the filter from the tab, and filter the widgets
1950
+ this.filter = $t.parent().data( 'filter' );
1951
+ this.filter.search = this.$( '.so-sidebar-search' ).val();
1952
+
1953
+ var message = $t.parent().data( 'message' );
1954
+ if ( _.isEmpty( message ) ) {
1955
+ message = '';
1956
+ }
1957
+
1958
+ this.$( '.so-toolbar .so-status' ).html( message );
1959
+
1960
+ this.filterWidgets( this.filter );
1961
+
1962
+ return false;
1963
+ },
1964
+
1965
+ /**
1966
+ * Handle changes to the search value
1967
+ */
1968
+ searchHandler: function ( e ) {
1969
+ if( e.which === 13 ) {
1970
+ var visibleWidgets = this.$( '.widget-type-list .widget-type:visible' );
1971
+ if( visibleWidgets.length === 1 ) {
1972
+ visibleWidgets.click();
1973
+ }
1974
+ }
1975
+ else {
1976
+ this.filter.search = $( e.target ).val().trim();
1977
+ this.filterWidgets( this.filter );
1978
+ }
1979
+ },
1980
+
1981
+ /**
1982
+ * Filter the widgets that we're displaying
1983
+ * @param filter
1984
+ */
1985
+ filterWidgets: function ( filter ) {
1986
+ if ( _.isUndefined( filter ) ) {
1987
+ filter = {};
1988
+ }
1989
+
1990
+ if ( _.isUndefined( filter.groups ) ) {
1991
+ filter.groups = '';
1992
+ }
1993
+
1994
+ this.$( '.widget-type-list .widget-type' ).each( function () {
1995
+ var $$ = $( this ), showWidget;
1996
+ var widgetClass = $$.data( 'class' );
1997
+
1998
+ var widgetData = (
1999
+ ! _.isUndefined( panelsOptions.widgets[widgetClass] )
2000
+ ) ? panelsOptions.widgets[widgetClass] : null;
2001
+
2002
+ if ( _.isEmpty( filter.groups ) ) {
2003
+ // This filter doesn't specify groups, so show all
2004
+ showWidget = true;
2005
+ } else if ( widgetData !== null && ! _.isEmpty( _.intersection( filter.groups, panelsOptions.widgets[widgetClass].groups ) ) ) {
2006
+ // This widget is in the filter group
2007
+ showWidget = true;
2008
+ } else {
2009
+ // This widget is not in the filter group
2010
+ showWidget = false;
2011
+ }
2012
+
2013
+ // This can probably be done with a more intelligent operator
2014
+ if ( showWidget ) {
2015
+
2016
+ if ( ! _.isUndefined( filter.search ) && filter.search !== '' ) {
2017
+ // Check if the widget title contains the search term
2018
+ if ( widgetData.title.toLowerCase().indexOf( filter.search.toLowerCase() ) === - 1 ) {
2019
+ showWidget = false;
2020
+ }
2021
+ }
2022
+
2023
+ }
2024
+
2025
+ if ( showWidget ) {
2026
+ $$.show();
2027
+ } else {
2028
+ $$.hide();
2029
+ }
2030
+ } );
2031
+
2032
+ // Balance the tags after filtering
2033
+ this.balanceWidgetHeights();
2034
+ },
2035
+
2036
+ /**
2037
+ * Add the widget to the current builder
2038
+ *
2039
+ * @param e
2040
+ */
2041
+ widgetClickHandler: function ( e ) {
2042
+ // Add the history entry
2043
+ this.builder.addHistoryEntry( 'widget_added' );
2044
+
2045
+ var $w = $( e.currentTarget );
2046
+
2047
+ var widget = new panels.model.widget( {
2048
+ class: $w.data( 'class' )
2049
+ } );
2050
+
2051
+ // Add the widget to the cell model
2052
+ widget.cell = this.builder.getActiveCell();
2053
+ widget.cell.get('widgets').add( widget );
2054
+
2055
+ this.closeDialog();
2056
+ this.builder.model.refreshPanelsData();
2057
+ },
2058
+
2059
+ /**
2060
+ * Balance widgets in a given row so they have enqual height.
2061
+ * @param e
2062
+ */
2063
+ balanceWidgetHeights: function ( e ) {
2064
+ var widgetRows = [[]];
2065
+ var previousWidget = null;
2066
+
2067
+ // Work out how many widgets there are per row
2068
+ var perRow = Math.round( this.$( '.widget-type' ).parent().width() / this.$( '.widget-type' ).width() );
2069
+
2070
+ // Add clears to create balanced rows
2071
+ this.$( '.widget-type' )
2072
+ .css( 'clear', 'none' )
2073
+ .filter( ':visible' )
2074
+ .each( function ( i, el ) {
2075
+ if ( i % perRow === 0 && i !== 0 ) {
2076
+ $( el ).css( 'clear', 'both' );
2077
+ }
2078
+ } );
2079
+
2080
+ // Group the widgets into rows
2081
+ this.$( '.widget-type-wrapper' )
2082
+ .css( 'height', 'auto' )
2083
+ .filter( ':visible' )
2084
+ .each( function ( i, el ) {
2085
+ var $el = $( el );
2086
+ if ( previousWidget !== null && previousWidget.position().top !== $el.position().top ) {
2087
+ widgetRows[widgetRows.length] = [];
2088
+ }
2089
+ previousWidget = $el;
2090
+ widgetRows[widgetRows.length - 1].push( $el );
2091
+ } );
2092
+
2093
+ // Balance the height of the widgets within the row.
2094
+ _.each( widgetRows, function ( row, i ) {
2095
+ var maxHeight = _.max( row.map( function ( el ) {
2096
+ return el.height();
2097
+ } ) );
2098
+ // Set the height of each widget in the row
2099
+ _.each( row, function ( el ) {
2100
+ el.height( maxHeight );
2101
+ } );
2102
+
2103
+ } );
2104
+ }
2105
+ } );
2106
+
2107
+ },{}],11:[function(require,module,exports){
2108
+ module.exports = {
2109
+ /**
2110
+ * Check if we have copy paste available.
2111
+ * @returns {boolean|*}
2112
+ */
2113
+ canCopyPaste: function(){
2114
+ return typeof(Storage) !== "undefined" && panelsOptions.user;
2115
+ },
2116
+
2117
+ /**
2118
+ * Set the model that we're going to store in the clipboard
2119
+ */
2120
+ setModel: function( model ){
2121
+ if( ! this.canCopyPaste() ) {
2122
+ return false;
2123
+ }
2124
+
2125
+ var serial = panels.helpers.serialize.serialize( model );
2126
+ if( model instanceof panels.model.row ) {
2127
+ serial.thingType = 'row-model';
2128
+ } else if( model instanceof panels.model.widget ) {
2129
+ serial.thingType = 'widget-model';
2130
+ }
2131
+
2132
+ // Store this in local storage
2133
+ localStorage[ 'panels_clipboard_' + panelsOptions.user ] = JSON.stringify( serial );
2134
+ return true;
2135
+ },
2136
+
2137
+ /**
2138
+ * Check if the current model stored in the clipboard is the expected type
2139
+ */
2140
+ isModel: function( expected ){
2141
+ if( ! this.canCopyPaste() ) {
2142
+ return false;
2143
+ }
2144
+
2145
+ var clipboardObject = localStorage[ 'panels_clipboard_' + panelsOptions.user ];
2146
+ if( clipboardObject !== undefined ) {
2147
+ clipboardObject = JSON.parse(clipboardObject);
2148
+ return clipboardObject.thingType && clipboardObject.thingType === expected;
2149
+ }
2150
+
2151
+ return false;
2152
+ },
2153
+
2154
+ /**
2155
+ * Get the model currently stored in the clipboard
2156
+ */
2157
+ getModel: function( expected ){
2158
+ if( ! this.canCopyPaste() ) {
2159
+ return null;
2160
+ }
2161
+
2162
+ var clipboardObject = localStorage[ 'panels_clipboard_' + panelsOptions.user ];
2163
+ if( clipboardObject !== undefined ) {
2164
+ clipboardObject = JSON.parse( clipboardObject );
2165
+ if( clipboardObject.thingType && clipboardObject.thingType === expected ) {
2166
+ return panels.helpers.serialize.unserialize( clipboardObject, clipboardObject.thingType, null );
2167
+ }
2168
+ }
2169
+
2170
+ return null;
2171
+ },
2172
+ };
2173
+
2174
+ },{}],12:[function(require,module,exports){
2175
+ module.exports = {
2176
+ /**
2177
+ * Lock window scrolling for the main overlay
2178
+ */
2179
+ lock: function () {
2180
+ if ( jQuery( 'body' ).css( 'overflow' ) === 'hidden' ) {
2181
+ return;
2182
+ }
2183
+
2184
+ // lock scroll position, but retain settings for later
2185
+ var scrollPosition = [
2186
+ self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
2187
+ self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
2188
+ ];
2189
+
2190
+ jQuery( 'body' )
2191
+ .data( {
2192
+ 'scroll-position': scrollPosition
2193
+ } )
2194
+ .css( 'overflow', 'hidden' );
2195
+
2196
+ if( ! _.isUndefined( scrollPosition ) ) {
2197
+ window.scrollTo( scrollPosition[0], scrollPosition[1] );
2198
+ }
2199
+ },
2200
+
2201
+ /**
2202
+ * Unlock window scrolling
2203
+ */
2204
+ unlock: function () {
2205
+ if ( jQuery( 'body' ).css( 'overflow' ) !== 'hidden' ) {
2206
+ return;
2207
+ }
2208
+
2209
+ // Check that there are no more dialogs or a live editor
2210
+ if ( ! jQuery( '.so-panels-dialog-wrapper' ).is( ':visible' ) && ! jQuery( '.so-panels-live-editor' ).is( ':visible' ) ) {
2211
+ jQuery( 'body' ).css( 'overflow', 'visible' );
2212
+ var scrollPosition = jQuery( 'body' ).data( 'scroll-position' );
2213
+
2214
+ if( ! _.isUndefined( scrollPosition ) ) {
2215
+ window.scrollTo( scrollPosition[0], scrollPosition[1] );
2216
+ }
2217
+ }
2218
+ },
2219
+ };
2220
+
2221
+ },{}],13:[function(require,module,exports){
2222
+ /*
2223
+ This is a modified version of https://github.com/underdogio/backbone-serialize/
2224
+ */
2225
+
2226
+ /* global Backbone, module, panels */
2227
+
2228
+ module.exports = {
2229
+ serialize: function( thing ){
2230
+ var val;
2231
+
2232
+ if( thing instanceof Backbone.Model ) {
2233
+ var retObj = {};
2234
+ for ( var key in thing.attributes ) {
2235
+ if (thing.attributes.hasOwnProperty( key ) ) {
2236
+ // Skip these to avoid recursion
2237
+ if( key === 'builder' || key === 'collection' ) { continue; }
2238
+
2239
+ // If the value is a Model or a Collection, then serialize them as well
2240
+ val = thing.attributes[key];
2241
+ if ( val instanceof Backbone.Model || val instanceof Backbone.Collection ) {
2242
+ retObj[key] = this.serialize( val );
2243
+ } else {
2244
+ // Otherwise, save the original value
2245
+ retObj[key] = val;
2246
+ }
2247
+ }
2248
+ }
2249
+ return retObj;
2250
+ }
2251
+ else if( thing instanceof Backbone.Collection ) {
2252
+ // Walk over all of our models
2253
+ var retArr = [];
2254
+
2255
+ for ( var i = 0; i < thing.models.length; i++ ) {
2256
+ // If the model is serializable, then serialize it
2257
+ val = thing.models[i];
2258
+
2259
+ if ( val instanceof Backbone.Model || val instanceof Backbone.Collection ) {
2260
+ retArr.push( this.serialize( val ) );
2261
+ } else {
2262
+ // Otherwise (it is an object), return it in its current form
2263
+ retArr.push( val );
2264
+ }
2265
+ }
2266
+
2267
+ // Return the serialized models
2268
+ return retArr;
2269
+ }
2270
+ },
2271
+
2272
+ unserialize: function( thing, thingType, parent ) {
2273
+ var retObj;
2274
+
2275
+ switch( thingType ) {
2276
+ case 'row-model' :
2277
+ retObj = new panels.model.row();
2278
+ retObj.builder = parent;
2279
+ retObj.set( 'style', thing.style );
2280
+ retObj.setCells( this.unserialize( thing.cells, 'cell-collection', retObj ) );
2281
+ break;
2282
+
2283
+ case 'cell-model' :
2284
+ retObj = new panels.model.cell();
2285
+ retObj.row = parent;
2286
+ retObj.set( 'weight', thing.weight );
2287
+ retObj.set( 'style', thing.style );
2288
+ retObj.set( 'widgets', this.unserialize( thing.widgets, 'widget-collection', retObj ) );
2289
+ break;
2290
+
2291
+ case 'widget-model' :
2292
+ retObj = new panels.model.widget();
2293
+ retObj.cell = parent;
2294
+ for ( var key in thing ) {
2295
+ if ( thing.hasOwnProperty( key ) ) {
2296
+ retObj.set( key, thing[key] );
2297
+ }
2298
+ }
2299
+ retObj.set( 'widget_id', panels.helpers.utils.generateUUID() );
2300
+ break;
2301
+
2302
+ case 'cell-collection':
2303
+ retObj = new panels.collection.cells();
2304
+ for( var i = 0; i < thing.length; i++ ) {
2305
+ retObj.push( this.unserialize( thing[i], 'cell-model', parent ) );
2306
+ }
2307
+ break;
2308
+
2309
+ case 'widget-collection':
2310
+ retObj = new panels.collection.widgets();
2311
+ for( var i = 0; i < thing.length; i++ ) {
2312
+ retObj.push( this.unserialize( thing[i], 'widget-model', parent ) );
2313
+ }
2314
+ break;
2315
+
2316
+ default:
2317
+ console.log( 'Unknown Thing - ' + thingType );
2318
+ break;
2319
+ }
2320
+
2321
+ return retObj;
2322
+ }
2323
+ };
2324
+
2325
+ },{}],14:[function(require,module,exports){
2326
+ module.exports = {
2327
+
2328
+ generateUUID: function(){
2329
+ var d = new Date().getTime();
2330
+ if( window.performance && typeof window.performance.now === "function" ){
2331
+ d += performance.now(); //use high-precision timer if available
2332
+ }
2333
+ var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace( /[xy]/g, function(c) {
2334
+ var r = (d + Math.random()*16)%16 | 0;
2335
+ d = Math.floor(d/16);
2336
+ return ( c == 'x' ? r : (r&0x3|0x8) ).toString(16);
2337
+ } );
2338
+ return uuid;
2339
+ },
2340
+
2341
+ processTemplate: function ( s ) {
2342
+ if ( _.isUndefined( s ) || _.isNull( s ) ) {
2343
+ return '';
2344
+ }
2345
+ s = s.replace( /{{%/g, '<%' );
2346
+ s = s.replace( /%}}/g, '%>' );
2347
+ s = s.trim();
2348
+ return s;
2349
+ },
2350
+
2351
+ // From this SO post: http://stackoverflow.com/questions/6139107/programmatically-select-text-in-a-contenteditable-html-element
2352
+ selectElementContents: function( element ) {
2353
+ var range = document.createRange();
2354
+ range.selectNodeContents( element );
2355
+ var sel = window.getSelection();
2356
+ sel.removeAllRanges();
2357
+ sel.addRange( range );
2358
+ },
2359
+
2360
+ }
2361
+
2362
+ },{}],15:[function(require,module,exports){
2363
+ /* global _, jQuery, panels */
2364
+
2365
+ var panels = window.panels, $ = jQuery;
2366
+
2367
+ module.exports = function ( config ) {
2368
+
2369
+ return this.each( function () {
2370
+ var $$ = jQuery( this );
2371
+ var widgetId = $$.closest( 'form' ).find( '.widget-id' ).val();
2372
+
2373
+ // Create a config for this specific widget
2374
+ var thisConfig = $.extend(true, {}, config);
2375
+
2376
+ // Exit if this isn't a real widget
2377
+ if ( ! _.isUndefined( widgetId ) && widgetId.indexOf( '__i__' ) > - 1 ) {
2378
+ return;
2379
+ }
2380
+
2381
+ // Create the main builder model
2382
+ var builderModel = new panels.model.builder();
2383
+
2384
+ // Now for the view to display the builder
2385
+ var builderView = new panels.view.builder( {
2386
+ model: builderModel,
2387
+ config: thisConfig
2388
+ } );
2389
+
2390
+ // Save panels data when we close the dialog, if we're in a dialog
2391
+ var dialog = $$.closest( '.so-panels-dialog-wrapper' ).data( 'view' );
2392
+ if ( ! _.isUndefined( dialog ) ) {
2393
+ dialog.on( 'close_dialog', function () {
2394
+ builderModel.refreshPanelsData();
2395
+ } );
2396
+
2397
+ dialog.on( 'open_dialog_complete', function () {
2398
+ // Make sure the new layout widget is always properly setup
2399
+ builderView.trigger( 'builder_resize' );
2400
+ } );
2401
+
2402
+ dialog.model.on( 'destroy', function () {
2403
+ // Destroy the builder
2404
+ builderModel.emptyRows().destroy();
2405
+ } );
2406
+
2407
+ // Set the parent for all the sub dialogs
2408
+ builderView.setDialogParents( panelsOptions.loc.layout_widget, dialog );
2409
+ }
2410
+
2411
+ // Basic setup for the builder
2412
+ var isWidget = Boolean( $$.closest( '.widget-content' ).length );
2413
+ builderView
2414
+ .render()
2415
+ .attach( {
2416
+ container: $$,
2417
+ dialog: isWidget || $$.data('mode') === 'dialog',
2418
+ type: $$.data( 'type' )
2419
+ } )
2420
+ .setDataField( $$.find( 'input.panels-data' ) );
2421
+
2422
+ if ( isWidget || $$.data('mode') === 'dialog' ) {
2423
+ // Set up the dialog opening
2424
+ builderView.setDialogParents( panelsOptions.loc.layout_widget, builderView.dialog );
2425
+ $$.find( '.siteorigin-panels-display-builder' ).click( function ( e ) {
2426
+ e.preventDefault();
2427
+ builderView.dialog.openDialog();
2428
+ } );
2429
+ } else {
2430
+ // Remove the dialog opener button, this is already being displayed in a page builder dialog.
2431
+ $$.find( '.siteorigin-panels-display-builder' ).parent().remove();
2432
+ }
2433
+
2434
+ // Trigger a global jQuery event after we've setup the builder view
2435
+ $( document ).trigger( 'panels_setup', builderView );
2436
+ } );
2437
+ };
2438
+
2439
+ },{}],16:[function(require,module,exports){
2440
+ /**
2441
+ * Everything we need for SiteOrigin Page Builder.
2442
+ *
2443
+ * @copyright Greg Priday 2013 - 2016 - <https://siteorigin.com/>
2444
+ * @license GPL 3.0 http://www.gnu.org/licenses/gpl.html
2445
+ */
2446
+
2447
+ /* global Backbone, _, jQuery, tinyMCE, panelsOptions, plupload, confirm, console, require */
2448
+
2449
+ var panels = {};
2450
+
2451
+ // Store everything globally
2452
+ window.panels = panels;
2453
+ window.siteoriginPanels = panels;
2454
+
2455
+ // Helpers
2456
+ panels.helpers = {};
2457
+ panels.helpers.clipboard = require( './helpers/clipboard' );
2458
+ panels.helpers.utils = require( './helpers/utils' );
2459
+ panels.helpers.serialize = require( './helpers/serialize' );
2460
+ panels.helpers.pageScroll = require( './helpers/page-scroll' );
2461
+
2462
+ // The models
2463
+ panels.model = {};
2464
+ panels.model.widget = require( './model/widget' );
2465
+ panels.model.cell = require( './model/cell' );
2466
+ panels.model.row = require( './model/row' );
2467
+ panels.model.builder = require( './model/builder' );
2468
+ panels.model.historyEntry = require( './model/history-entry' );
2469
+
2470
+ // The collections
2471
+ panels.collection = {};
2472
+ panels.collection.widgets = require( './collection/widgets' );
2473
+ panels.collection.cells = require( './collection/cells' );
2474
+ panels.collection.rows = require( './collection/rows' );
2475
+ panels.collection.historyEntries = require( './collection/history-entries' );
2476
+
2477
+ // The views
2478
+ panels.view = {};
2479
+ panels.view.widget = require( './view/widget' );
2480
+ panels.view.cell = require( './view/cell' );
2481
+ panels.view.row = require( './view/row' );
2482
+ panels.view.builder = require( './view/builder' );
2483
+ panels.view.dialog = require( './view/dialog' );
2484
+ panels.view.styles = require( './view/styles' );
2485
+ panels.view.liveEditor = require( './view/live-editor' );
2486
+
2487
+ // The dialogs
2488
+ panels.dialog = {};
2489
+ panels.dialog.builder = require( './dialog/builder' );
2490
+ panels.dialog.widgets = require( './dialog/widgets' );
2491
+ panels.dialog.widget = require( './dialog/widget' );
2492
+ panels.dialog.prebuilt = require( './dialog/prebuilt' );
2493
+ panels.dialog.row = require( './dialog/row' );
2494
+ panels.dialog.history = require( './dialog/history' );
2495
+
2496
+ // The utils
2497
+ panels.utils = {};
2498
+ panels.utils.menu = require( './utils/menu' );
2499
+
2500
+ // jQuery Plugins
2501
+ jQuery.fn.soPanelsSetupBuilderWidget = require( './jquery/setup-builder-widget' );
2502
+
2503
+
2504
+ // Set up Page Builder if we're on the main interface
2505
+ jQuery( function ( $ ) {
2506
+
2507
+ var container,
2508
+ field,
2509
+ form,
2510
+ builderConfig;
2511
+
2512
+ var $panelsMetabox = $( '#siteorigin-panels-metabox' );
2513
+ form = $( 'form#post' );
2514
+ if ( $panelsMetabox.length && form.length ) {
2515
+ // This is usually the case when we're in the post edit interface
2516
+ container = $panelsMetabox;
2517
+ field = $panelsMetabox.find( '.siteorigin-panels-data-field' );
2518
+
2519
+ builderConfig = {
2520
+ editorType: 'tinyMCE',
2521
+ postId: $( '#post_ID' ).val(),
2522
+ editorId: '#content',
2523
+ builderType: $panelsMetabox.data( 'builder-type' ),
2524
+ builderSupports: $panelsMetabox.data( 'builder-supports' ),
2525
+ loadOnAttach: panelsOptions.loadOnAttach && $( '#auto_draft' ).val() == 1,
2526
+ loadLiveEditor: $panelsMetabox.data('live-editor') == 1,
2527
+ liveEditorPreview: container.data('preview-url')
2528
+ };
2529
+ }
2530
+ else if ( $( '.siteorigin-panels-builder-form' ).length ) {
2531
+ // We're dealing with another interface like the custom home page interface
2532
+ var $$ = $( '.siteorigin-panels-builder-form' );
2533
+
2534
+ container = $$.find( '.siteorigin-panels-builder-container' );
2535
+ field = $$.find( 'input[name="panels_data"]' );
2536
+ form = $$;
2537
+
2538
+ builderConfig = {
2539
+ editorType: 'standalone',
2540
+ postId: $$.data( 'post-id' ),
2541
+ editorId: '#post_content',
2542
+ builderType: $$.data( 'type' ),
2543
+ builderSupports: $$.data( 'builder-supports' ),
2544
+ loadLiveEditor: false,
2545
+ liveEditorPreview: $$.data( 'preview-url' )
2546
+ };
2547
+ }
2548
+
2549
+ if ( ! _.isUndefined( container ) ) {
2550
+ // If we have a container, then set up the main builder
2551
+ var panels = window.siteoriginPanels;
2552
+
2553
+ // Create the main builder model
2554
+ var builderModel = new panels.model.builder();
2555
+
2556
+ // Now for the view to display the builder
2557
+ var builderView = new panels.view.builder( {
2558
+ model: builderModel,
2559
+ config: builderConfig
2560
+ } );
2561
+
2562
+ // Set up the builder view
2563
+ builderView
2564
+ .render()
2565
+ .attach( {
2566
+ container: container
2567
+ } )
2568
+ .setDataField( field )
2569
+ .attachToEditor();
2570
+
2571
+ // When the form is submitted, update the panels data
2572
+ form.submit( function () {
2573
+ // Refresh the data
2574
+ builderModel.refreshPanelsData();
2575
+ } );
2576
+
2577
+ container.removeClass( 'so-panels-loading' );
2578
+
2579
+ // Trigger a global jQuery event after we've setup the builder view. Everything is accessible form there
2580
+ $( document ).trigger( 'panels_setup', builderView, window.panels );
2581
+ }
2582
+
2583
+ // Setup new widgets when they're added in the standard widget interface
2584
+ $( document ).on( 'widget-added', function ( e, widget ) {
2585
+ $( widget ).find( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
2586
+ } );
2587
+
2588
+ // Setup existing widgets on the page (for the widgets interface)
2589
+ if ( ! $( 'body' ).hasClass( 'wp-customizer' ) ) {
2590
+ $( function () {
2591
+ $( '.siteorigin-page-builder-widget' ).soPanelsSetupBuilderWidget();
2592
+ } );
2593
+ }
2594
+ } );
2595
+
2596
+ },{"./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(require,module,exports){
2597
+ module.exports = Backbone.Model.extend({
2598
+ layoutPosition: {
2599
+ BEFORE: 'before',
2600
+ AFTER: 'after',
2601
+ REPLACE: 'replace',
2602
+ },
2603
+
2604
+ rows: {},
2605
+
2606
+ defaults: {
2607
+ 'data': {
2608
+ 'widgets': [],
2609
+ 'grids': [],
2610
+ 'grid_cells': []
2611
+ }
2612
+ },
2613
+
2614
+ initialize: function () {
2615
+ // These are the main rows in the interface
2616
+ this.set( 'rows', new panels.collection.rows() );
2617
+ },
2618
+
2619
+ /**
2620
+ * Add a new row to this builder.
2621
+ *
2622
+ * @param attrs
2623
+ * @param cells
2624
+ * @param options
2625
+ */
2626
+ addRow: function (attrs, cells, options) {
2627
+ options = _.extend({
2628
+ noAnimate: false
2629
+ }, options);
2630
+
2631
+ var cellCollection = new panels.collection.cells(cells);
2632
+
2633
+ attrs = _.extend({
2634
+ collection: this.get('rows'),
2635
+ cells: cellCollection,
2636
+ }, attrs);
2637
+
2638
+ // Create the actual row
2639
+ var row = new panels.model.row(attrs);
2640
+ row.builder = this;
2641
+
2642
+ this.get('rows').add( row, options );
2643
+
2644
+ return row;
2645
+ },
2646
+
2647
+ /**
2648
+ * Load the panels data into the builder
2649
+ *
2650
+ * @param data Object the layout and widgets data to load.
2651
+ * @param position string Where to place the new layout. Allowed options are 'before', 'after'. Anything else will
2652
+ * cause the new layout to replace the old one.
2653
+ */
2654
+ loadPanelsData: function ( data, position ) {
2655
+ try {
2656
+ if ( position === this.layoutPosition.BEFORE ) {
2657
+ data = this.concatPanelsData( data, this.getPanelsData() );
2658
+ } else if ( position === this.layoutPosition.AFTER ) {
2659
+ data = this.concatPanelsData( this.getPanelsData(), data );
2660
+ }
2661
+
2662
+ // Start by destroying any rows that currently exist. This will in turn destroy cells, widgets and all the associated views
2663
+ this.emptyRows();
2664
+
2665
+ // This will empty out the current rows and reload the builder data.
2666
+ this.set( 'data', JSON.parse( JSON.stringify( data ) ), {silent: true} );
2667
+
2668
+ var cit = 0;
2669
+ var rows = [];
2670
+
2671
+ if ( _.isUndefined( data.grid_cells ) ) {
2672
+ this.trigger( 'load_panels_data' );
2673
+ return;
2674
+ }
2675
+
2676
+ var gi;
2677
+ for ( var ci = 0; ci < data.grid_cells.length; ci ++ ) {
2678
+ gi = parseInt( data.grid_cells[ci].grid );
2679
+ if ( _.isUndefined( rows[gi] ) ) {
2680
+ rows[gi] = [];
2681
+ }
2682
+
2683
+ rows[gi].push( data.grid_cells[ci] );
2684
+ }
2685
+
2686
+ var builderModel = this;
2687
+ _.each( rows, function ( row, i ) {
2688
+ var rowAttrs = {};
2689
+
2690
+ if ( ! _.isUndefined( data.grids[i].style ) ) {
2691
+ rowAttrs.style = data.grids[i].style;
2692
+ }
2693
+
2694
+ if ( ! _.isUndefined( data.grids[i].ratio) ) {
2695
+ rowAttrs.ratio = data.grids[i].ratio;
2696
+ }
2697
+
2698
+ if ( ! _.isUndefined( data.grids[i].ratio_direction) ) {
2699
+ rowAttrs.ratio_direction = data.grids[i].ratio_direction
2700
+ }
2701
+
2702
+ if ( ! _.isUndefined( data.grids[i].color_label) ) {
2703
+ rowAttrs.color_label = data.grids[i].color_label;
2704
+ }
2705
+
2706
+ if ( ! _.isUndefined( data.grids[i].label) ) {
2707
+ rowAttrs.label = data.grids[i].label;
2708
+ }
2709
+ // This will create and add the row model and its cells
2710
+ builderModel.addRow(rowAttrs, row, {noAnimate: true} );
2711
+ } );
2712
+
2713
+
2714
+ if ( _.isUndefined( data.widgets ) ) {
2715
+ return;
2716
+ }
2717
+
2718
+ // Add the widgets
2719
+ _.each( data.widgets, function ( widgetData ) {
2720
+ var panels_info = null;
2721
+ if ( ! _.isUndefined( widgetData.panels_info ) ) {
2722
+ panels_info = widgetData.panels_info;
2723
+ delete widgetData.panels_info;
2724
+ } else {
2725
+ panels_info = widgetData.info;
2726
+ delete widgetData.info;
2727
+ }
2728
+
2729
+ var row = builderModel.get('rows').at( parseInt( panels_info.grid ) );
2730
+ var cell = row.get('cells').at( parseInt( panels_info.cell ) );
2731
+
2732
+ var newWidget = new panels.model.widget( {
2733
+ class: panels_info.class,
2734
+ values: widgetData
2735
+ } );
2736
+
2737
+ if ( ! _.isUndefined( panels_info.style ) ) {
2738
+ newWidget.set( 'style', panels_info.style );
2739
+ }
2740
+
2741
+ if ( ! _.isUndefined( panels_info.read_only ) ) {
2742
+ newWidget.set( 'read_only', panels_info.read_only );
2743
+ }
2744
+ if ( ! _.isUndefined( panels_info.widget_id ) ) {
2745
+ newWidget.set( 'widget_id', panels_info.widget_id );
2746
+ }
2747
+ else {
2748
+ newWidget.set( 'widget_id', panels.helpers.utils.generateUUID() );
2749
+ }
2750
+
2751
+ if ( ! _.isUndefined( panels_info.label ) ) {
2752
+ newWidget.set( 'label', panels_info.label );
2753
+ }
2754
+
2755
+ newWidget.cell = cell;
2756
+ cell.get('widgets').add( newWidget, { noAnimate: true } );
2757
+ } );
2758
+
2759
+ this.trigger( 'load_panels_data' );
2760
+ }
2761
+ catch ( err ) {
2762
+ console.log( 'Error loading data: ' + err.message );
2763
+
2764
+ }
2765
+ },
2766
+
2767
+ /**
2768
+ * Concatenate the second set of Page Builder data to the first. There is some validation of input, but for the most
2769
+ * part it's up to the caller to ensure the Page Builder data is well formed.
2770
+ */
2771
+ concatPanelsData: function ( panelsDataA, panelsDataB ) {
2772
+
2773
+ if ( _.isUndefined( panelsDataB ) || _.isUndefined( panelsDataB.grids ) || _.isEmpty( panelsDataB.grids ) ||
2774
+ _.isUndefined( panelsDataB.grid_cells ) || _.isEmpty( panelsDataB.grid_cells ) ) {
2775
+ return panelsDataA;
2776
+ }
2777
+
2778
+ if ( _.isUndefined( panelsDataA ) || _.isUndefined( panelsDataA.grids ) || _.isEmpty( panelsDataA.grids ) ) {
2779
+ return panelsDataB;
2780
+ }
2781
+
2782
+ var gridsBOffset = panelsDataA.grids.length;
2783
+ var widgetsBOffset = ! _.isUndefined( panelsDataA.widgets ) ? panelsDataA.widgets.length : 0;
2784
+ var newPanelsData = {grids: [], 'grid_cells': [], 'widgets': []};
2785
+
2786
+ // Concatenate grids (rows)
2787
+ newPanelsData.grids = panelsDataA.grids.concat( panelsDataB.grids );
2788
+
2789
+ // Create a copy of panelsDataA grid_cells and widgets
2790
+ if ( ! _.isUndefined( panelsDataA.grid_cells ) ) {
2791
+ newPanelsData.grid_cells = panelsDataA.grid_cells.slice();
2792
+ }
2793
+ if ( ! _.isUndefined( panelsDataA.widgets ) ) {
2794
+ newPanelsData.widgets = panelsDataA.widgets.slice();
2795
+ }
2796
+
2797
+ var i;
2798
+ // Concatenate grid cells (row columns)
2799
+ for ( i = 0; i < panelsDataB.grid_cells.length; i ++ ) {
2800
+ var gridCellB = panelsDataB.grid_cells[i];
2801
+ gridCellB.grid = parseInt( gridCellB.grid ) + gridsBOffset;
2802
+ newPanelsData.grid_cells.push( gridCellB );
2803
+ }
2804
+
2805
+ // Concatenate widgets
2806
+ if ( ! _.isUndefined( panelsDataB.widgets ) ) {
2807
+ for ( i = 0; i < panelsDataB.widgets.length; i ++ ) {
2808
+ var widgetB = panelsDataB.widgets[i];
2809
+ widgetB.panels_info.grid = parseInt( widgetB.panels_info.grid ) + gridsBOffset;
2810
+ widgetB.panels_info.id = parseInt( widgetB.panels_info.id ) + widgetsBOffset;
2811
+ newPanelsData.widgets.push( widgetB );
2812
+ }
2813
+ }
2814
+
2815
+ return newPanelsData;
2816
+ },
2817
+
2818
+ /**
2819
+ * Convert the content of the builder into a object that represents the page builder data
2820
+ */
2821
+ getPanelsData: function () {
2822
+
2823
+ var builder = this;
2824
+
2825
+ var data = {
2826
+ 'widgets': [],
2827
+ 'grids': [],
2828
+ 'grid_cells': []
2829
+ };
2830
+ var widgetId = 0;
2831
+
2832
+ this.get('rows').each( function ( row, ri ) {
2833
+
2834
+ row.get('cells').each( function ( cell, ci ) {
2835
+
2836
+ cell.get('widgets').each( function ( widget, wi ) {
2837
+ // Add the data for the widget, including the panels_info field.
2838
+ var panels_info = {
2839
+ class: widget.get( 'class' ),
2840
+ raw: widget.get( 'raw' ),
2841
+ grid: ri,
2842
+ cell: ci,
2843
+ // Strictly this should be an index
2844
+ id: widgetId ++,
2845
+ widget_id: widget.get( 'widget_id' ),
2846
+ style: widget.get( 'style' ),
2847
+ label: widget.get( 'label' ),
2848
+ };
2849
+
2850
+ if( _.isEmpty( panels_info.widget_id ) ) {
2851
+ panels_info.widget_id = panels.helpers.utils.generateUUID();
2852
+ }
2853
+
2854
+ var values = _.extend( _.clone( widget.get( 'values' ) ), {
2855
+ panels_info: panels_info
2856
+ } );
2857
+ data.widgets.push( values );
2858
+ } );
2859
+
2860
+ // Add the cell info
2861
+ data.grid_cells.push( {
2862
+ grid: ri,
2863
+ index: ci,
2864
+ weight: cell.get( 'weight' ),
2865
+ style: cell.get( 'style' ),
2866
+ } );
2867
+
2868
+ } );
2869
+
2870
+ data.grids.push( {
2871
+ cells: row.get('cells').length,
2872
+ style: row.get( 'style' ),
2873
+ ratio: row.get('ratio'),
2874
+ ratio_direction: row.get('ratio_direction'),
2875
+ color_label: row.get( 'color_label' ),
2876
+ label: row.get( 'label' ),
2877
+ } );
2878
+
2879
+ } );
2880
+
2881
+ return data;
2882
+
2883
+ },
2884
+
2885
+ /**
2886
+ * This will check all the current entries and refresh the panels data
2887
+ */
2888
+ refreshPanelsData: function ( args ) {
2889
+ args = _.extend( {
2890
+ silent: false
2891
+ }, args );
2892
+
2893
+ var oldData = this.get( 'data' );
2894
+ var newData = this.getPanelsData();
2895
+ this.set( 'data', newData, {silent: true} );
2896
+
2897
+ if ( ! args.silent && JSON.stringify( newData ) !== JSON.stringify( oldData ) ) {
2898
+ // The default change event doesn't trigger on deep changes, so we'll trigger our own
2899
+ this.trigger( 'change' );
2900
+ this.trigger( 'change:data' );
2901
+ this.trigger( 'refresh_panels_data', newData, args );
2902
+ }
2903
+ },
2904
+
2905
+ /**
2906
+ * Empty all the rows and the cells/widgets they contain.
2907
+ */
2908
+ emptyRows: function () {
2909
+ _.invoke( this.get('rows').toArray(), 'destroy' );
2910
+ this.get('rows').reset();
2911
+
2912
+ return this;
2913
+ },
2914
+
2915
+ isValidLayoutPosition: function ( position ) {
2916
+ return position === this.layoutPosition.BEFORE ||
2917
+ position === this.layoutPosition.AFTER ||
2918
+ position === this.layoutPosition.REPLACE;
2919
+ },
2920
+
2921
+ /**
2922
+ * Convert HTML into Panels Data
2923
+ * @param html
2924
+ */
2925
+ getPanelsDataFromHtml: function( html, editorClass ){
2926
+ var thisModel = this;
2927
+ var $html = jQuery( '<div id="wrapper">' + html + '</div>' );
2928
+
2929
+ if( $html.find('.panel-layout .panel-grid').length ) {
2930
+ // This looks like Page Builder html, lets try parse it
2931
+ var panels_data = {
2932
+ grids: [],
2933
+ grid_cells: [],
2934
+ widgets: [],
2935
+ };
2936
+
2937
+ // The Regex object that'll match SiteOrigin widgets
2938
+ var re = new RegExp( panelsOptions.siteoriginWidgetRegex , "i" );
2939
+ var decodeEntities = (function() {
2940
+ // this prevents any overhead from creating the object each time
2941
+ var element = document.createElement('div');
2942
+
2943
+ function decodeHTMLEntities (str) {
2944
+ if(str && typeof str === 'string') {
2945
+ // strip script/html tags
2946
+ str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
2947
+ str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
2948
+ element.innerHTML = str;
2949
+ str = element.textContent;
2950
+ element.textContent = '';
2951
+ }
2952
+
2953
+ return str;
2954
+ }
2955
+
2956
+ return decodeHTMLEntities;
2957
+ })();
2958
+
2959
+ // Remove all wrapping divs from a widget to get its html
2960
+ var getTextWidgetContents = function( $el ){
2961
+ var $divs = $el.find( 'div' );
2962
+ if( ! $divs.length ) {
2963
+ return $el.html();
2964
+ }
2965
+
2966
+ var i;
2967
+ for( i = 0; i < $divs.length - 1; i++ ) {
2968
+ if( jQuery.trim( $divs.eq(i).text() ) != jQuery.trim( $divs.eq(i+1).text() ) ) {
2969
+ break;
2970
+ }
2971
+ }
2972
+
2973
+ var title = $divs.eq( i ).find( '.widget-title:header' ),
2974
+ titleText = '';
2975
+
2976
+ if( title.length ) {
2977
+ titleText = title.html();
2978
+ title.remove();
2979
+ }
2980
+
2981
+ return {
2982
+ title: titleText,
2983
+ text: $divs.eq(i).html(),
2984
+ };
2985
+ };
2986
+
2987
+ var $layout = $html.find( '.panel-layout' ).eq(0);
2988
+ var filterNestedLayout = function( i, el ){
2989
+ return jQuery( el ).closest( '.panel-layout' ).is( $layout );
2990
+ };
2991
+
2992
+ $html.find('> .panel-layout > .panel-grid').filter( filterNestedLayout ).each( function( ri, el ){
2993
+ var $row = jQuery( el ),
2994
+ $cells = $row.find( '.panel-grid-cell' ).filter( filterNestedLayout );
2995
+
2996
+ panels_data.grids.push( {
2997
+ cells: $cells.length,
2998
+ style: $row.data( 'style' ),
2999
+ ratio: $row.data( 'ratio' ),
3000
+ ratio_direction: $row.data( 'ratio-direction' ),
3001
+ color_label: $row.data( 'color-label' ),
3002
+ label: $row.data( 'label' ),
3003
+ } );
3004
+
3005
+ $cells.each( function( ci, el ){
3006
+ var $cell = jQuery( el ),
3007
+ $widgets = $cell.find( '.so-panel' ).filter( filterNestedLayout );
3008
+
3009
+ panels_data.grid_cells.push( {
3010
+ grid: ri,
3011
+ weight: ! _.isUndefined( $cell.data( 'weight' ) ) ? parseFloat( $cell.data( 'weight' ) ) : 1,
3012
+ style: $cell.data( 'style' ),
3013
+ } );
3014
+
3015
+ $widgets.each( function( wi, el ){
3016
+ var $widget = jQuery(el),
3017
+ widgetContent = $widget.find('.panel-widget-style').length ? $widget.find('.panel-widget-style').html() : $widget.html(),
3018
+ panels_info = {
3019
+ grid: ri,
3020
+ cell: ci,
3021
+ style: $widget.data( 'style' ),
3022
+ raw: false,
3023
+ label: $widget.data( 'label' )
3024
+ };
3025
+
3026
+ widgetContent = widgetContent.trim();
3027
+
3028
+ // Check if this is a SiteOrigin Widget
3029
+ var match = re.exec( widgetContent );
3030
+ if( ! _.isNull( match ) && widgetContent.replace( re, '' ).trim() === '' ) {
3031
+ try {
3032
+ var classMatch = /class="(.*?)"/.exec( match[3] ),
3033
+ dataInput = jQuery( match[5] ),
3034
+ data = JSON.parse( decodeEntities( dataInput.val( ) ) ),
3035
+ newWidget = data.instance;
3036
+
3037
+ panels_info.class = classMatch[1].replace( /\\\\+/g, '\\' );
3038
+ panels_info.raw = false;
3039
+
3040
+ newWidget.panels_info = panels_info;
3041
+ panels_data.widgets.push( newWidget );
3042
+ }
3043
+ catch ( err ) {
3044
+ // There was a problem, so treat this as a standard editor widget
3045
+ panels_info.class = editorClass;
3046
+ panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
3047
+ filter: "1",
3048
+ type: "visual",
3049
+ panels_info: panels_info
3050
+ } ) );
3051
+ }
3052
+
3053
+ // Continue
3054
+ return true;
3055
+ }
3056
+ else if( widgetContent.indexOf( 'panel-layout' ) !== -1 ) {
3057
+ // Check if this is a layout widget
3058
+ var $widgetContent = jQuery( '<div>' + widgetContent + '</div>' );
3059
+ if( $widgetContent.find('.panel-layout .panel-grid').length ) {
3060
+ // This is a standard editor class widget
3061
+ panels_info.class = 'SiteOrigin_Panels_Widgets_Layout';
3062
+ panels_data.widgets.push( {
3063
+ panels_data: thisModel.getPanelsDataFromHtml( widgetContent, editorClass ),
3064
+ panels_info: panels_info
3065
+ } );
3066
+
3067
+ // continue
3068
+ return true;
3069
+ }
3070
+ }
3071
+
3072
+ // This is a standard editor class widget
3073
+ panels_info.class = editorClass;
3074
+ panels_data.widgets.push( _.extend( getTextWidgetContents( $widget ), {
3075
+ filter: "1",
3076
+ type: "visual",
3077
+ panels_info: panels_info
3078
+ } ) );
3079
+ return true;
3080
+ } );
3081
+ } );
3082
+ } );
3083
+
3084
+ // Remove all the Page Builder content
3085
+ $html.find('.panel-layout').remove();
3086
+ $html.find('style[data-panels-style-for-post]').remove();
3087
+
3088
+ // If there's anything left, add it to an editor widget at the end of panels_data
3089
+ if( $html.html().replace(/^\s+|\s+$/gm,'').length ) {
3090
+ panels_data.grids.push( {
3091
+ cells: 1,
3092
+ style: {},
3093
+ } );
3094
+ panels_data.grid_cells.push( {
3095
+ grid: panels_data.grids.length - 1,
3096
+ weight: 1,
3097
+ } );
3098
+ panels_data.widgets.push( {
3099
+ filter: "1",
3100
+ text: $html.html().replace(/^\s+|\s+$/gm,''),
3101
+ title: "",
3102
+ type: "visual",
3103
+ panels_info: {
3104
+ class: editorClass,
3105
+ raw: false,
3106
+ grid: panels_data.grids.length - 1,
3107
+ cell: 0
3108
+ }
3109
+ } );
3110
+ }
3111
+
3112
+ return panels_data;
3113
+ }
3114
+ else {
3115
+ // This is probably just old school post content
3116
+ return {
3117
+ grid_cells: [ { grid: 0, weight: 1 } ],
3118
+ grids: [ { cells: 1 } ],
3119
+ widgets: [
3120
+ {
3121
+ filter: "1",
3122
+ text: html,
3123
+ title: "",
3124
+ type: "visual",
3125
+ panels_info: {
3126
+ class: editorClass,
3127
+ raw: false,
3128
+ grid: 0,
3129
+ cell: 0
3130
+ }
3131
+ }
3132
+ ]
3133
+ };
3134
+ }
3135
+ }
3136
+ } );
3137
+
3138
+ },{}],18:[function(require,module,exports){
3139
+ module.exports = Backbone.Model.extend( {
3140
+ /* A collection of widgets */
3141
+ widgets: {},
3142
+
3143
+ /* The row this model belongs to */
3144
+ row: null,
3145
+
3146
+ defaults: {
3147
+ weight: 0,
3148
+ style: {}
3149
+ },
3150
+
3151
+ indexes: null,
3152
+
3153
+ /**
3154
+ * Set up the cell model
3155
+ */
3156
+ initialize: function () {
3157
+ this.set( 'widgets', new panels.collection.widgets() );
3158
+ this.on( 'destroy', this.onDestroy, this );
3159
+ },
3160
+
3161
+ /**
3162
+ * Triggered when we destroy a cell
3163
+ */
3164
+ onDestroy: function () {
3165
+ // Destroy all the widgets
3166
+ _.invoke( this.get('widgets').toArray(), 'destroy' );
3167
+ this.get('widgets').reset();
3168
+ },
3169
+
3170
+ /**
3171
+ * Create a clone of the cell, along with all its widgets
3172
+ */
3173
+ clone: function ( row, cloneOptions ) {
3174
+ if ( _.isUndefined( row ) ) {
3175
+ row = this.row;
3176
+ }
3177
+ cloneOptions = _.extend( {cloneWidgets: true}, cloneOptions );
3178
+
3179
+ var clone = new this.constructor( this.attributes );
3180
+ clone.set( 'collection', row.get('cells'), {silent: true} );
3181
+ clone.row = row;
3182
+
3183
+ if ( cloneOptions.cloneWidgets ) {
3184
+ // Now we're going add all the widgets that belong to this, to the clone
3185
+ this.get('widgets').each( function ( widget ) {
3186
+ clone.get('widgets').add( widget.clone( clone, cloneOptions ), {silent: true} );
3187
+ } );
3188
+ }
3189
+
3190
+ return clone;
3191
+ }
3192
+
3193
+ } );
3194
+
3195
+ },{}],19:[function(require,module,exports){
3196
+ module.exports = Backbone.Model.extend( {
3197
+ defaults: {
3198
+ text: '',
3199
+ data: '',
3200
+ time: null,
3201
+ count: 1
3202
+ }
3203
+ } );
3204
+
3205
+ },{}],20:[function(require,module,exports){
3206
+ module.exports = Backbone.Model.extend( {
3207
+ /* The builder model */
3208
+ builder: null,
3209
+
3210
+ defaults: {
3211
+ style: {}
3212
+ },
3213
+
3214
+ indexes: null,
3215
+
3216
+ /**
3217
+ * Initialize the row model
3218
+ */
3219
+ initialize: function () {
3220
+ if ( _.isEmpty(this.get('cells') ) ) {
3221
+ this.set('cells', new panels.collection.cells());
3222
+ }
3223
+ else {
3224
+ // Make sure that the cells have this row set as their parent
3225
+ this.get('cells').each( function( cell ){
3226
+ cell.row = this;
3227
+ }.bind( this ) );
3228
+ }
3229
+ this.on( 'destroy', this.onDestroy, this );
3230
+ },
3231
+
3232
+ /**
3233
+ * Add cells to the model row
3234
+ *
3235
+ * @param newCells the updated collection of cell models
3236
+ */
3237
+ setCells: function ( newCells ) {
3238
+ var currentCells = this.get('cells') || new panels.collection.cells();
3239
+ var cellsToRemove = [];
3240
+
3241
+ currentCells.each(function (cell, i) {
3242
+ var newCell = newCells.at(i);
3243
+ if(newCell) {
3244
+ cell.set('weight', newCell.get('weight'));
3245
+ } else {
3246
+ var newParentCell = currentCells.at( newCells.length - 1 );
3247
+
3248
+ // First move all the widgets to the new cell
3249
+ var widgetsToMove = cell.get('widgets').models.slice();
3250
+ for ( var j = 0; j < widgetsToMove.length; j++ ) {
3251
+ widgetsToMove[j].moveToCell( newParentCell, { silent: false } );
3252
+ }
3253
+
3254
+ cellsToRemove.push(cell);
3255
+ }
3256
+ });
3257
+
3258
+ _.each(cellsToRemove, function(cell) {
3259
+ currentCells.remove(cell);
3260
+ });
3261
+
3262
+ if( newCells.length > currentCells.length) {
3263
+ _.each(newCells.slice(currentCells.length, newCells.length), function (newCell) {
3264
+ // TODO: make sure row and collection is set correctly when cell is created then we can just add new cells
3265
+ newCell.set({collection: currentCells});
3266
+ newCell.row = this;
3267
+ currentCells.add(newCell);
3268
+ }.bind(this));
3269
+ }
3270
+
3271
+ // Rescale the cells when we add or remove
3272
+ this.reweightCells();
3273
+ },
3274
+
3275
+ /**
3276
+ * Make sure that all the cell weights add up to 1
3277
+ */
3278
+ reweightCells: function () {
3279
+ var totalWeight = 0;
3280
+ var cells = this.get('cells');
3281
+ cells.each( function ( cell ) {
3282
+ totalWeight += cell.get( 'weight' );
3283
+ } );
3284
+
3285
+ cells.each( function ( cell ) {
3286
+ cell.set( 'weight', cell.get( 'weight' ) / totalWeight );
3287
+ } );
3288
+
3289
+ // This is for the row view to hook into and resize
3290
+ this.trigger( 'reweight_cells' );
3291
+ },
3292
+
3293
+ /**
3294
+ * Triggered when the model is destroyed
3295
+ */
3296
+ onDestroy: function () {
3297
+ // Also destroy all the cells
3298
+ _.invoke( this.get('cells').toArray(), 'destroy' );
3299
+ this.get('cells').reset();
3300
+ },
3301
+
3302
+ /**
3303
+ * Create a clone of the row, along with all its cells
3304
+ *
3305
+ * @param {panels.model.builder} builder The builder model to attach this to.
3306
+ *
3307
+ * @return {panels.model.row} The cloned row.
3308
+ */
3309
+ clone: function ( builder ) {
3310
+ if ( _.isUndefined( builder ) ) {
3311
+ builder = this.builder;
3312
+ }
3313
+
3314
+ var clone = new this.constructor( this.attributes );
3315
+ clone.set( 'collection', builder.get('rows'), {silent: true} );
3316
+ clone.builder = builder;
3317
+
3318
+ var cellClones = new panels.collection.cells();
3319
+ this.get('cells').each( function ( cell ) {
3320
+ cellClones.add( cell.clone( clone ), {silent: true} );
3321
+ } );
3322
+
3323
+ clone.set( 'cells', cellClones );
3324
+
3325
+ return clone;
3326
+ }
3327
+ } );
3328
+
3329
+ },{}],21:[function(require,module,exports){
3330
+ /**
3331
+ * Model for an instance of a widget
3332
+ */
3333
+ module.exports = Backbone.Model.extend( {
3334
+
3335
+ cell: null,
3336
+
3337
+ defaults: {
3338
+ // The PHP Class of the widget
3339
+ class: null,
3340
+
3341
+ // Is this class missing? Missing widgets are a special case.
3342
+ missing: false,
3343
+
3344
+ // The values of the widget
3345
+ values: {},
3346
+
3347
+ // Have the current values been passed through the widgets update function
3348
+ raw: false,
3349
+
3350
+ // Visual style fields
3351
+ style: {},
3352
+
3353
+ read_only: false,
3354
+ widget_id: '',
3355
+ },
3356
+
3357
+ indexes: null,
3358
+
3359
+ initialize: function () {
3360
+ var widgetClass = this.get( 'class' );
3361
+ if ( _.isUndefined( panelsOptions.widgets[widgetClass] ) || ! panelsOptions.widgets[widgetClass].installed ) {
3362
+ this.set( 'missing', true );
3363
+ }
3364
+ },
3365
+
3366
+ /**
3367
+ * @param field
3368
+ * @returns {*}
3369
+ */
3370
+ getWidgetField: function ( field ) {
3371
+ if ( _.isUndefined( panelsOptions.widgets[this.get( 'class' )] ) ) {
3372
+ if ( field === 'title' || field === 'description' ) {
3373
+ return panelsOptions.loc.missing_widget[field];
3374
+ } else {
3375
+ return '';
3376
+ }
3377
+ } else if ( this.has( 'label' ) && ! _.isEmpty( this.get( 'label' ) ) ) {
3378
+ // Use the label instead of the actual widget title
3379
+ return this.get( 'label' );
3380
+ } else {
3381
+ return panelsOptions.widgets[ this.get( 'class' ) ][ field ];
3382
+ }
3383
+ },
3384
+
3385
+ /**
3386
+ * Move this widget model to a new cell. Called by the views.
3387
+ *
3388
+ * @param panels.model.cell newCell
3389
+ * @param object options The options passed to the
3390
+ *
3391
+ * @return boolean Indicating if the widget was moved into a different cell
3392
+ */
3393
+ moveToCell: function ( newCell, options, at ) {
3394
+ options = _.extend( {
3395
+ silent: true,
3396
+ }, options );
3397
+
3398
+ this.cell = newCell;
3399
+ this.collection.remove( this, options );
3400
+ newCell.get('widgets').add( this, _.extend( {
3401
+ at: at
3402
+ }, options ) );
3403
+
3404
+ // This should be used by views to reposition everything.
3405
+ this.trigger( 'move_to_cell', newCell, at );
3406
+
3407
+ return this;
3408
+ },
3409
+
3410
+ /**
3411
+ * Trigger an event on the model that indicates a user wants to edit it
3412
+ */
3413
+ triggerEdit: function () {
3414
+ this.trigger( 'user_edit', this );
3415
+ },
3416
+
3417
+ /**
3418
+ * Trigger an event on the widget that indicates a user wants to duplicate it
3419
+ */
3420
+ triggerDuplicate: function () {
3421
+ this.trigger( 'user_duplicate', this );
3422
+ },
3423
+
3424
+ /**
3425
+ * This is basically a wrapper for set that checks if we need to trigger a change
3426
+ */
3427
+ setValues: function ( values ) {
3428
+ var hasChanged = false;
3429
+ if ( JSON.stringify( values ) !== JSON.stringify( this.get( 'values' ) ) ) {
3430
+ hasChanged = true;
3431
+ }
3432
+
3433
+ this.set( 'values', values, {silent: true} );
3434
+
3435
+ if ( hasChanged ) {
3436
+ // We'll trigger our own change events.
3437
+ // NB: Must include the model being changed (i.e. `this`) as a workaround for a bug in Backbone 1.2.3
3438
+ this.trigger( 'change', this );
3439
+ this.trigger( 'change:values' );
3440
+ }
3441
+ },
3442
+
3443
+ /**
3444
+ * Create a clone of this widget attached to the given cell.
3445
+ *
3446
+ * @param {panels.model.cell} cell The cell model we're attaching this widget clone to.
3447
+ * @returns {panels.model.widget}
3448
+ */
3449
+ clone: function ( cell, options ) {
3450
+ if ( _.isUndefined( cell ) ) {
3451
+ cell = this.cell;
3452
+ }
3453
+
3454
+ var clone = new this.constructor( this.attributes );
3455
+
3456
+ // Create a deep clone of the original values
3457
+ var cloneValues = JSON.parse( JSON.stringify( this.get( 'values' ) ) );
3458
+
3459
+ // We want to exclude any fields that start with _ from the clone. Assuming these are internal.
3460
+ var cleanClone = function ( vals ) {
3461
+ _.each( vals, function ( el, i ) {
3462
+ if ( _.isString( i ) && i[0] === '_' ) {
3463
+ delete vals[i];
3464
+ }
3465
+ else if ( _.isObject( vals[i] ) ) {
3466
+ cleanClone( vals[i] );
3467
+ }
3468
+ } );
3469
+
3470
+ return vals;
3471
+ };
3472
+ cloneValues = cleanClone( cloneValues );
3473
+
3474
+ if ( this.get( 'class' ) === "SiteOrigin_Panels_Widgets_Layout" ) {
3475
+ // Special case of this being a layout widget, it needs a new ID
3476
+ cloneValues.builder_id = Math.random().toString( 36 ).substr( 2 );
3477
+ }
3478
+
3479
+ clone.set( 'widget_id', '' );
3480
+ clone.set( 'values', cloneValues, {silent: true} );
3481
+ clone.set( 'collection', cell.get('widgets'), {silent: true} );
3482
+ clone.cell = cell;
3483
+
3484
+ // This is used to force a form reload later on
3485
+ clone.isDuplicate = true;
3486
+
3487
+ return clone;
3488
+ },
3489
+
3490
+ /**
3491
+ * Gets the value that makes most sense as the title.
3492
+ */
3493
+ getTitle: function () {
3494
+ var widgetData = panelsOptions.widgets[this.get( 'class' )];
3495
+
3496
+ if ( _.isUndefined( widgetData ) ) {
3497
+ return this.get( 'class' ).replace( /_/g, ' ' );
3498
+ }
3499
+ else if ( ! _.isUndefined( widgetData.panels_title ) ) {
3500
+ // This means that the widget has told us which field it wants us to use as a title
3501
+ if ( widgetData.panels_title === false ) {
3502
+ return panelsOptions.widgets[this.get( 'class' )].description;
3503
+ }
3504
+ }
3505
+
3506
+ var values = this.get( 'values' );
3507
+
3508
+ // Create a list of fields to check for a title
3509
+ var titleFields = ['title', 'text'];
3510
+
3511
+ for ( var k in values ) {
3512
+ if ( values.hasOwnProperty( k ) ) {
3513
+ titleFields.push( k );
3514
+ }
3515
+ }
3516
+
3517
+ titleFields = _.uniq( titleFields );
3518
+
3519
+ for ( var i in titleFields ) {
3520
+ if (
3521
+ ! _.isUndefined( values[titleFields[i]] ) &&
3522
+ _.isString( values[titleFields[i]] ) &&
3523
+ values[titleFields[i]] !== '' &&
3524
+ values[titleFields[i]] !== 'on' &&
3525
+ titleFields[i][0] !== '_' && ! jQuery.isNumeric( values[titleFields[i]] )
3526
+ ) {
3527
+ var title = values[titleFields[i]];
3528
+ title = title.replace( /<\/?[^>]+(>|$)/g, "" );
3529
+ var parts = title.split( " " );
3530
+ parts = parts.slice( 0, 20 );
3531
+ return parts.join( ' ' );
3532
+ }
3533
+ }
3534
+
3535
+ // If we still have nothing, then just return the widget description
3536
+ return this.getWidgetField( 'description' );
3537
+ }
3538
+
3539
+ } );
3540
+
3541
+ },{}],22:[function(require,module,exports){
3542
+ var panels = window.panels, $ = jQuery;
3543
+
3544
+ module.exports = Backbone.View.extend( {
3545
+ wrapperTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu' ).html() ) ),
3546
+ sectionTemplate: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-context-menu-section' ).html() ) ),
3547
+
3548
+ contexts: [],
3549
+ active: false,
3550
+
3551
+ events: {
3552
+ 'keyup .so-search-wrapper input': 'searchKeyUp'
3553
+ },
3554
+
3555
+ /**
3556
+ * Intialize the context menu
3557
+ */
3558
+ initialize: function () {
3559
+ this.listenContextMenu();
3560
+ this.render();
3561
+ this.attach();
3562
+ },
3563
+
3564
+ /**
3565
+ * Listen for the right click context menu
3566
+ */
3567
+ listenContextMenu: function () {
3568
+ var thisView = this;
3569
+
3570
+ $( window ).on( 'contextmenu', function ( e ) {
3571
+ if ( thisView.active && ! thisView.isOverEl( thisView.$el, e ) ) {
3572
+ thisView.closeMenu();
3573
+ thisView.active = false;
3574
+ e.preventDefault();
3575
+ return false;
3576
+ }
3577
+
3578
+ if ( thisView.active ) {
3579
+ // Lets not double up on the context menu
3580
+ return true;
3581
+ }
3582
+
3583
+ // Other components should listen to activate_context
3584
+ thisView.active = false;
3585
+ thisView.trigger( 'activate_context', e, thisView );
3586
+
3587
+ if ( thisView.active ) {
3588
+ // We don't want the default event to happen.
3589
+ e.preventDefault();
3590
+
3591
+ thisView.openMenu( {
3592
+ left: e.pageX,
3593
+ top: e.pageY
3594
+ } );
3595
+ }
3596
+ } );
3597
+ },
3598
+
3599
+ render: function () {
3600
+ this.setElement( this.wrapperTemplate() );
3601
+ },
3602
+
3603
+ attach: function () {
3604
+ this.$el.appendTo( 'body' );
3605
+ },
3606
+
3607
+ /**
3608
+ * Display the actual context menu.
3609
+ *
3610
+ * @param position
3611
+ */
3612
+ openMenu: function ( position ) {
3613
+ this.trigger( 'open_menu' );
3614
+
3615
+ // Start listening for situations when we should close the menu
3616
+ $( window ).on( 'keyup', {menu: this}, this.keyboardListen );
3617
+ $( window ).on( 'click', {menu: this}, this.clickOutsideListen );
3618
+
3619
+ // Set the maximum height of the menu
3620
+ this.$el.css( 'max-height', $( window ).height() - 20 );
3621
+
3622
+ // Correct the left position
3623
+ if ( position.left + this.$el.outerWidth() + 10 >= $( window ).width() ) {
3624
+ position.left = $( window ).width() - this.$el.outerWidth() - 10;
3625
+ }
3626
+ if ( position.left <= 0 ) {
3627
+ position.left = 10;
3628
+ }
3629
+
3630
+ // Check top position
3631
+ if ( position.top + this.$el.outerHeight() - $( window ).scrollTop() + 10 >= $( window ).height() ) {
3632
+ position.top = $( window ).height() + $( window ).scrollTop() - this.$el.outerHeight() - 10;
3633
+ }
3634
+ if ( position.left <= 0 ) {
3635
+ position.left = 10;
3636
+ }
3637
+
3638
+ // position the contextual menu
3639
+ this.$el.css( {
3640
+ left: position.left + 1,
3641
+ top: position.top + 1
3642
+ } ).show();
3643
+ this.$( '.so-search-wrapper input' ).focus();
3644
+ },
3645
+
3646
+ closeMenu: function () {
3647
+ this.trigger( 'close_menu' );
3648
+
3649
+ // Stop listening for situations when we should close the menu
3650
+ $( window ).off( 'keyup', this.keyboardListen );
3651
+ $( window ).off( 'click', this.clickOutsideListen );
3652
+
3653
+ this.active = false;
3654
+ this.$el.empty().hide();
3655
+ },
3656
+
3657
+ /**
3658
+ * Keyboard events handler
3659
+ */
3660
+ keyboardListen: function ( e ) {
3661
+ var menu = e.data.menu;
3662
+
3663
+ switch ( e.which ) {
3664
+ case 27:
3665
+ menu.closeMenu();
3666
+ break;
3667
+ }
3668
+ },
3669
+
3670
+ /**
3671
+ * Listen for a click outside the menu to close it.
3672
+ * @param e
3673
+ */
3674
+ clickOutsideListen: function ( e ) {
3675
+ var menu = e.data.menu;
3676
+ if ( e.which !== 3 && menu.$el.is( ':visible' ) && ! menu.isOverEl( menu.$el, e ) ) {
3677
+ menu.closeMenu();
3678
+ }
3679
+ },
3680
+
3681
+ /**
3682
+ * Add a new section to the contextual menu.
3683
+ *
3684
+ * @param settings
3685
+ * @param items
3686
+ * @param callback
3687
+ */
3688
+ addSection: function ( id, settings, items, callback ) {
3689
+ var thisView = this;
3690
+ settings = _.extend( {
3691
+ display: 5,
3692
+ defaultDisplay: false,
3693
+ search: true,
3694
+
3695
+ // All the labels
3696
+ sectionTitle: '',
3697
+ searchPlaceholder: '',
3698
+
3699
+ // This is the key to be used in items for the title. Makes it easier to list objects
3700
+ titleKey: 'title'
3701
+ }, settings );
3702
+
3703
+ // Create the new section
3704
+ var section = $( this.sectionTemplate( {
3705
+ settings: settings,
3706
+ items: items
3707
+ } ) ).attr( 'id', 'panels-menu-section-' + id );
3708
+ this.$el.append( section );
3709
+
3710
+ section.find( '.so-item:not(.so-confirm)' ).click( function () {
3711
+ var $$ = $( this );
3712
+ callback( $$.data( 'key' ) );
3713
+ thisView.closeMenu();
3714
+ } );
3715
+
3716
+ section.find( '.so-item.so-confirm' ).click( function () {
3717
+ var $$ = $( this );
3718
+
3719
+ if ( $$.hasClass( 'so-confirming' ) ) {
3720
+ callback( $$.data( 'key' ) );
3721
+ thisView.closeMenu();
3722
+ return;
3723
+ }
3724
+
3725
+ $$
3726
+ .data( 'original-text', $$.html() )
3727
+ .addClass( 'so-confirming' )
3728
+ .html( '<span class="dashicons dashicons-yes"></span> ' + panelsOptions.loc.dropdown_confirm );
3729
+
3730
+ setTimeout( function () {
3731
+ $$.removeClass( 'so-confirming' );
3732
+ $$.html( $$.data( 'original-text' ) );
3733
+ }, 2500 );
3734
+ } );
3735
+
3736
+ section.data( 'settings', settings ).find( '.so-search-wrapper input' ).trigger( 'keyup' );
3737
+
3738
+ this.active = true;
3739
+ },
3740
+
3741
+ /**
3742
+ * Check if a section exists in the current menu.
3743
+ *
3744
+ * @param id
3745
+ * @returns {boolean}
3746
+ */
3747
+ hasSection: function( id ){
3748
+ return this.$el.find( '#panels-menu-section-' + id ).length > 0;
3749
+ },
3750
+
3751
+ /**
3752
+ * Handle searching inside a section.
3753
+ *
3754
+ * @param e
3755
+ * @returns {boolean}
3756
+ */
3757
+ searchKeyUp: function ( e ) {
3758
+ var
3759
+ $$ = $( e.currentTarget ),
3760
+ section = $$.closest( '.so-section' ),
3761
+ settings = section.data( 'settings' );
3762
+
3763
+ if ( e.which === 38 || e.which === 40 ) {
3764
+ // First, lets check if this is an up, down or enter press
3765
+ var
3766
+ items = section.find( 'ul li:visible' ),
3767
+ activeItem = items.filter( '.so-active' ).eq( 0 );
3768
+
3769
+ if ( activeItem.length ) {
3770
+ items.removeClass( 'so-active' );
3771
+
3772
+ var activeIndex = items.index( activeItem );
3773
+
3774
+ if ( e.which === 38 ) {
3775
+ if ( activeIndex - 1 < 0 ) {
3776
+ activeItem = items.last();
3777
+ } else {
3778
+ activeItem = items.eq( activeIndex - 1 );
3779
+ }
3780
+ }
3781
+ else if ( e.which === 40 ) {
3782
+ if ( activeIndex + 1 >= items.length ) {
3783
+ activeItem = items.first();
3784
+ } else {
3785
+ activeItem = items.eq( activeIndex + 1 );
3786
+ }
3787
+ }
3788
+ }
3789
+ else if ( e.which === 38 ) {
3790
+ activeItem = items.last();
3791
+ }
3792
+ else if ( e.which === 40 ) {
3793
+ activeItem = items.first();
3794
+ }
3795
+
3796
+ activeItem.addClass( 'so-active' );
3797
+ return false;
3798
+ }
3799
+ if ( e.which === 13 ) {
3800
+ if ( section.find( 'ul li:visible' ).length === 1 ) {
3801
+ // We'll treat a single visible item as active when enter is clicked
3802
+ section.find( 'ul li:visible' ).trigger( 'click' );
3803
+ return false;
3804
+ }
3805
+ section.find( 'ul li.so-active:visible' ).trigger( 'click' );
3806
+ return false;
3807
+ }
3808
+
3809
+ if ( $$.val() === '' ) {
3810
+ // We'll display the defaultDisplay items
3811
+ if ( settings.defaultDisplay ) {
3812
+ section.find( '.so-item' ).hide();
3813
+ for ( var i = 0; i < settings.defaultDisplay.length; i ++ ) {
3814
+ section.find( '.so-item[data-key="' + settings.defaultDisplay[i] + '"]' ).show();
3815
+ }
3816
+ } else {
3817
+ // We'll just display all the items
3818
+ section.find( '.so-item' ).show();
3819
+ }
3820
+ } else {
3821
+ section.find( '.so-item' ).hide().each( function () {
3822
+ var item = $( this );
3823
+ if ( item.html().toLowerCase().indexOf( $$.val().toLowerCase() ) !== - 1 ) {
3824
+ item.show();
3825
+ }
3826
+ } );
3827
+ }
3828
+
3829
+ // Now, we'll only show the first settings.display visible items
3830
+ section.find( '.so-item:visible:gt(' + (
3831
+ settings.display - 1
3832
+ ) + ')' ).hide();
3833
+
3834
+
3835
+ if ( section.find( '.so-item:visible' ).length === 0 && $$.val() !== '' ) {
3836
+ section.find( '.so-no-results' ).show();
3837
+ } else {
3838
+ section.find( '.so-no-results' ).hide();
3839
+ }
3840
+ },
3841
+
3842
+ /**
3843
+ * Check if the given mouse event is over the element
3844
+ * @param el
3845
+ * @param event
3846
+ */
3847
+ isOverEl: function ( el, event ) {
3848
+ var elPos = [
3849
+ [el.offset().left, el.offset().top],
3850
+ [el.offset().left + el.outerWidth(), el.offset().top + el.outerHeight()]
3851
+ ];
3852
+
3853
+ // Return if this event is over the given element
3854
+ return (
3855
+ event.pageX >= elPos[0][0] && event.pageX <= elPos[1][0] &&
3856
+ event.pageY >= elPos[0][1] && event.pageY <= elPos[1][1]
3857
+ );
3858
+ }
3859
+
3860
+ } );
3861
+
3862
+ },{}],23:[function(require,module,exports){
3863
+ var panels = window.panels, $ = jQuery;
3864
+
3865
+ module.exports = Backbone.View.extend( {
3866
+
3867
+ // Config options
3868
+ config: {},
3869
+
3870
+ template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder' ).html() ) ),
3871
+ dialogs: {},
3872
+ rowsSortable: null,
3873
+ dataField: false,
3874
+ currentData: '',
3875
+
3876
+ attachedToEditor: false,
3877
+ attachedVisible: false,
3878
+ liveEditor: undefined,
3879
+ menu: false,
3880
+
3881
+ activeCell: null,
3882
+
3883
+ events: {
3884
+ 'click .so-tool-button.so-widget-add': 'displayAddWidgetDialog',
3885
+ 'click .so-tool-button.so-row-add': 'displayAddRowDialog',
3886
+ 'click .so-tool-button.so-prebuilt-add': 'displayAddPrebuiltDialog',
3887
+ 'click .so-tool-button.so-history': 'displayHistoryDialog',
3888
+ 'click .so-tool-button.so-live-editor': 'displayLiveEditor'
3889
+ },
3890
+
3891
+ /* A row collection */
3892
+ rows: null,
3893
+
3894
+ /**
3895
+ * Initialize the builder
3896
+ */
3897
+ initialize: function ( options ) {
3898
+ var builder = this;
3899
+
3900
+ this.config = _.extend( {
3901
+ loadLiveEditor: false,
3902
+ builderSupports: {}
3903
+ }, options.config );
3904
+
3905
+ // These are the actions that a user can perform in the builder
3906
+ this.config.builderSupports = _.extend( {
3907
+ addRow: true,
3908
+ editRow: true,
3909
+ deleteRow: true,
3910
+ moveRow: true,
3911
+ addWidget: true,
3912
+ editWidget: true,
3913
+ deleteWidget: true,
3914
+ moveWidget: true,
3915
+ prebuilt: true,
3916
+ history: true,
3917
+ liveEditor: true,
3918
+ revertToEditor: true
3919
+ }, this.config.builderSupports );
3920
+
3921
+ // Automatically load the live editor as soon as it's ready
3922
+ if ( options.config.loadLiveEditor ) {
3923
+ this.on( 'builder_live_editor_added', function () {
3924
+ this.displayLiveEditor();
3925
+ } );
3926
+ }
3927
+
3928
+ // Now lets create all the dialog boxes that the main builder interface uses
3929
+ this.dialogs = {
3930
+ widgets: new panels.dialog.widgets(),
3931
+ row: new panels.dialog.row(),
3932
+ prebuilt: new panels.dialog.prebuilt()
3933
+ };
3934
+
3935
+ // Set the builder for each dialog and render it.
3936
+ _.each( this.dialogs, function ( p, i, d ) {
3937
+ d[ i ].setBuilder( builder );
3938
+ } );
3939
+
3940
+ this.dialogs.row.setRowDialogType( 'create' );
3941
+
3942
+ // This handles a new row being added to the collection - we'll display it in the interface
3943
+ this.model.get( 'rows' ).on( 'add', this.onAddRow, this );
3944
+
3945
+ // Reflow the entire builder when ever the
3946
+ $( window ).resize( function ( e ) {
3947
+ if ( e.target === window ) {
3948
+ builder.trigger( 'builder_resize' );
3949
+ }
3950
+ } );
3951
+
3952
+ // When the data changes in the model, store it in the field
3953
+ this.model.on( 'change:data load_panels_data', this.storeModelData, this );
3954
+
3955
+ // Handle a content change
3956
+ this.on( 'content_change', this.handleContentChange, this );
3957
+ this.on( 'display_builder', this.handleDisplayBuilder, this );
3958
+ this.on( 'hide_builder', this.handleHideBuilder, this );
3959
+ this.on( 'builder_rendered builder_resize', this.handleBuilderSizing, this );
3960
+ this.model.on( 'change:data load_panels_data', this.toggleWelcomeDisplay, this );
3961
+
3962
+ this.on( 'display_builder', this.wrapEditorExpandAdjust, this );
3963
+
3964
+ // Create the context menu for this builder
3965
+ this.menu = new panels.utils.menu( {} );
3966
+ this.menu.on( 'activate_context', this.activateContextMenu, this );
3967
+
3968
+ if ( this.config.loadOnAttach ) {
3969
+ this.on( 'builder_attached_to_editor', function () {
3970
+ this.displayAttachedBuilder( { confirm: false } );
3971
+ }, this );
3972
+ }
3973
+
3974
+
3975
+ return this;
3976
+ },
3977
+
3978
+ /**
3979
+ * Render the builder interface.
3980
+ *
3981
+ * @return {panels.view.builder}
3982
+ */
3983
+ render: function () {
3984
+ // this.$el.html( this.template() );
3985
+ this.setElement( this.template() );
3986
+ this.$el
3987
+ .attr( 'id', 'siteorigin-panels-builder-' + this.cid )
3988
+ .addClass( 'so-builder-container' );
3989
+
3990
+ this.trigger( 'builder_rendered' );
3991
+
3992
+ return this;
3993
+ },
3994
+
3995
+ /**
3996
+ * Attach the builder to the given container
3997
+ *
3998
+ * @param container
3999
+ * @returns {panels.view.builder}
4000
+ */
4001
+ attach: function ( options ) {
4002
+
4003
+ options = _.extend( {
4004
+ container: false,
4005
+ dialog: false
4006
+ }, options );
4007
+
4008
+ if ( options.dialog ) {
4009
+ // We're going to add this to a dialog
4010
+ this.dialog = new panels.dialog.builder();
4011
+ this.dialog.builder = this;
4012
+ } else {
4013
+ // Attach this in the standard way
4014
+ this.$el.appendTo( options.container );
4015
+ this.metabox = options.container.closest( '.postbox' );
4016
+ this.initSortable();
4017
+ this.trigger( 'attached_to_container', options.container );
4018
+ }
4019
+
4020
+ this.trigger( 'builder_attached' );
4021
+
4022
+ // Add support for components we have
4023
+
4024
+ if ( this.supports( 'liveEditor' ) ) {
4025
+ this.addLiveEditor();
4026
+ }
4027
+ if ( this.supports( 'history' ) ) {
4028
+ this.addHistoryBrowser();
4029
+ }
4030
+
4031
+ // Hide toolbar buttons we don't support
4032
+ var toolbar = this.$( '.so-builder-toolbar' );
4033
+ var welcomeMessageContainer = this.$( '.so-panels-welcome-message' );
4034
+ var welcomeMessage = panelsOptions.loc.welcomeMessage;
4035
+
4036
+ var supportedItems = [];
4037
+
4038
+ if ( !this.supports( 'addWidget' ) ) {
4039
+ toolbar.find( '.so-widget-add' ).hide();
4040
+ } else {
4041
+ supportedItems.push( welcomeMessage.addWidgetButton );
4042
+ }
4043
+ if ( !this.supports( 'addRow' ) ) {
4044
+ toolbar.find( '.so-row-add' ).hide();
4045
+ } else {
4046
+ supportedItems.push( welcomeMessage.addRowButton );
4047
+ }
4048
+ if ( !this.supports( 'prebuilt' ) ) {
4049
+ toolbar.find( '.so-prebuilt-add' ).hide();
4050
+ } else {
4051
+ supportedItems.push( welcomeMessage.addPrebuiltButton );
4052
+ }
4053
+
4054
+ var msg = '';
4055
+ if ( supportedItems.length === 3 ) {
4056
+ msg = welcomeMessage.threeEnabled;
4057
+ } else if ( supportedItems.length === 2 ) {
4058
+ msg = welcomeMessage.twoEnabled;
4059
+ } else if ( supportedItems.length === 1 ) {
4060
+ msg = welcomeMessage.oneEnabled;
4061
+ } else if ( supportedItems.length === 0 ) {
4062
+ msg = welcomeMessage.addingDisabled;
4063
+ }
4064
+
4065
+ var resTemplate = _.template( panels.helpers.utils.processTemplate( msg ) );
4066
+ var msgHTML = resTemplate( { items: supportedItems } ) + ' ' + welcomeMessage.docsMessage;
4067
+ welcomeMessageContainer.find( '.so-message-wrapper' ).html( msgHTML );
4068
+
4069
+ return this;
4070
+ },
4071
+
4072
+ /**
4073
+ * This will move the Page Builder meta box into the editor if we're in the post/page edit interface.
4074
+ *
4075
+ * @returns {panels.view.builder}
4076
+ */
4077
+ attachToEditor: function () {
4078
+ if ( this.config.editorType !== 'tinyMCE' ) {
4079
+ return this;
4080
+ }
4081
+
4082
+ this.attachedToEditor = true;
4083
+ var metabox = this.metabox;
4084
+ var thisView = this;
4085
+
4086
+ // Handle switching between the page builder and other tabs
4087
+ $( '#wp-content-wrap .wp-editor-tabs' )
4088
+ .find( '.wp-switch-editor' )
4089
+ .click( function ( e ) {
4090
+ e.preventDefault();
4091
+ $( '#wp-content-editor-container' ).show();
4092
+
4093
+ // metabox.hide();
4094
+ $( '#wp-content-wrap' ).removeClass( 'panels-active' );
4095
+ $( '#content-resize-handle' ).show();
4096
+
4097
+ // Make sure the word count is visible
4098
+ thisView.trigger( 'hide_builder' );
4099
+ } ).end()
4100
+ .append(
4101
+ $( '<a id="content-panels" class="hide-if-no-js wp-switch-editor switch-panels">' + metabox.find( '.hndle span' ).html() + '</a>' )
4102
+ .click( function ( e ) {
4103
+ if ( thisView.displayAttachedBuilder( { confirm: true } ) ) {
4104
+ e.preventDefault();
4105
+ }
4106
+ } )
4107
+ );
4108
+
4109
+ // Switch back to the standard editor
4110
+ if ( this.supports( 'revertToEditor' ) ) {
4111
+ metabox.find( '.so-switch-to-standard' ).click( function ( e ) {
4112
+ e.preventDefault();
4113
+
4114
+ if ( !confirm( panelsOptions.loc.confirm_stop_builder ) ) {
4115
+ return;
4116
+ }
4117
+
4118
+ // User is switching to the standard visual editor
4119
+ thisView.addHistoryEntry( 'back_to_editor' );
4120
+ thisView.model.loadPanelsData( false );
4121
+
4122
+ // Switch back to the standard editor
4123
+ $( '#wp-content-wrap' ).show();
4124
+ metabox.hide();
4125
+
4126
+ // Resize to trigger reflow of WordPress editor stuff
4127
+ $( window ).resize();
4128
+
4129
+ thisView.attachedVisible = false;
4130
+ thisView.trigger( 'hide_builder' );
4131
+ } ).show();
4132
+ }
4133
+
4134
+ // Move the panels box into a tab of the content editor
4135
+ metabox.insertAfter( '#wp-content-wrap' ).hide().addClass( 'attached-to-editor' );
4136
+
4137
+ // Switch to the Page Builder interface as soon as we load the page if there are widgets or the normal editor
4138
+ // isn't supported.
4139
+ var data = this.model.get( 'data' );
4140
+ if ( !_.isEmpty( data.widgets ) || !_.isEmpty( data.grids ) || !this.supports( 'revertToEditor' ) ) {
4141
+ this.displayAttachedBuilder( { confirm: false } );
4142
+ }
4143
+
4144
+ // We will also make this sticky if its attached to an editor.
4145
+ var stickToolbar = function () {
4146
+ var toolbar = thisView.$( '.so-builder-toolbar' );
4147
+
4148
+ if ( thisView.$el.hasClass( 'so-display-narrow' ) ) {
4149
+ // In this case, we don't want to stick the toolbar.
4150
+ toolbar.css( {
4151
+ top: 0,
4152
+ left: 0,
4153
+ width: '100%',
4154
+ position: 'absolute'
4155
+ } );
4156
+ thisView.$el.css( 'padding-top', toolbar.outerHeight() );
4157
+ return;
4158
+ }
4159
+
4160
+ var newTop = $( window ).scrollTop() - thisView.$el.offset().top;
4161
+
4162
+ if ( $( '#wpadminbar' ).css( 'position' ) === 'fixed' ) {
4163
+ newTop += $( '#wpadminbar' ).outerHeight();
4164
+ }
4165
+
4166
+ var limits = {
4167
+ top: 0,
4168
+ bottom: thisView.$el.outerHeight() - toolbar.outerHeight() + 20
4169
+ };
4170
+
4171
+ if ( newTop > limits.top && newTop < limits.bottom ) {
4172
+ if ( toolbar.css( 'position' ) !== 'fixed' ) {
4173
+ // The toolbar needs to stick to the top, over the interface
4174
+ toolbar.css( {
4175
+ top: $( '#wpadminbar' ).outerHeight(),
4176
+ left: thisView.$el.offset().left,
4177
+ width: thisView.$el.outerWidth(),
4178
+ position: 'fixed'
4179
+ } );
4180
+ }
4181
+ } else {
4182
+ // The toolbar needs to be at the top or bottom of the interface
4183
+ toolbar.css( {
4184
+ top: Math.min( Math.max( newTop, 0 ), thisView.$el.outerHeight() - toolbar.outerHeight() + 20 ),
4185
+ left: 0,
4186
+ width: '100%',
4187
+ position: 'absolute'
4188
+ } );
4189
+ }
4190
+
4191
+ thisView.$el.css( 'padding-top', toolbar.outerHeight() );
4192
+ };
4193
+
4194
+ this.on( 'builder_resize', stickToolbar, this );
4195
+ $( document ).scroll( stickToolbar );
4196
+ stickToolbar();
4197
+
4198
+ this.trigger( 'builder_attached_to_editor' );
4199
+
4200
+ return this;
4201
+ },
4202
+
4203
+ /**
4204
+ * Display the builder interface when attached to a WordPress editor
4205
+ */
4206
+ displayAttachedBuilder: function ( options ) {
4207
+ options = _.extend( {
4208
+ confirm: true
4209
+ }, options );
4210
+
4211
+ // Switch to the Page Builder interface
4212
+
4213
+ if ( options.confirm ) {
4214
+ var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
4215
+ var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
4216
+
4217
+ if ( editorContent !== '' && !confirm( panelsOptions.loc.confirm_use_builder ) ) {
4218
+ return false;
4219
+ }
4220
+ }
4221
+
4222
+ // Hide the standard content editor
4223
+ $( '#wp-content-wrap' ).hide();
4224
+
4225
+
4226
+ $( '#editor-expand-toggle' ).on( 'change.editor-expand', function () {
4227
+ if ( !$( this ).prop( 'checked' ) ) {
4228
+ $( '#wp-content-wrap' ).hide();
4229
+ }
4230
+ } );
4231
+
4232
+ // Show page builder and the inside div
4233
+ this.metabox.show().find( '> .inside' ).show();
4234
+
4235
+ // Triggers full refresh
4236
+ $( window ).resize();
4237
+ $( document ).scroll();
4238
+
4239
+ // Make sure the word count is visible
4240
+ this.attachedVisible = true;
4241
+ this.trigger( 'display_builder' );
4242
+
4243
+ return true;
4244
+ },
4245
+
4246
+ /**
4247
+ * Initialize the row sortables
4248
+ */
4249
+ initSortable: function () {
4250
+ if ( !this.supports( 'moveRow' ) ) {
4251
+ return this;
4252
+ }
4253
+
4254
+ // Create the sortable for the rows
4255
+ var builderView = this;
4256
+
4257
+ this.rowsSortable = this.$( '.so-rows-container' ).sortable( {
4258
+ appendTo: '#wpwrap',
4259
+ items: '.so-row-container',
4260
+ handle: '.so-row-move',
4261
+ axis: 'y',
4262
+ tolerance: 'pointer',
4263
+ scroll: false,
4264
+ stop: function ( e, ui ) {
4265
+ builderView.addHistoryEntry( 'row_moved' );
4266
+
4267
+ var $$ = $( ui.item ),
4268
+ row = $$.data( 'view' );
4269
+
4270
+ builderView.model.get( 'rows' ).remove( row.model, {
4271
+ 'silent': true
4272
+ } );
4273
+ builderView.model.get( 'rows' ).add( row.model, {
4274
+ 'silent': true,
4275
+ 'at': $$.index()
4276
+ } );
4277
+
4278
+ row.trigger( 'move', $$.index() );
4279
+
4280
+ builderView.model.refreshPanelsData();
4281
+ }
4282
+ } );
4283
+
4284
+ return this;
4285
+ },
4286
+
4287
+ /**
4288
+ * Refresh the row sortable
4289
+ */
4290
+ refreshSortable: function () {
4291
+ // Refresh the sortable to account for the new row
4292
+ if ( !_.isNull( this.rowsSortable ) ) {
4293
+ this.rowsSortable.sortable( 'refresh' );
4294
+ }
4295
+ },
4296
+
4297
+ /**
4298
+ * Set the field that's used to store the data
4299
+ * @param field
4300
+ */
4301
+ setDataField: function ( field, options ) {
4302
+ options = _.extend( {
4303
+ load: true
4304
+ }, options );
4305
+
4306
+ this.dataField = field;
4307
+ this.dataField.data( 'builder', this );
4308
+
4309
+ if ( options.load && field.val() !== '' ) {
4310
+ var data = this.dataField.val();
4311
+ try {
4312
+ data = JSON.parse( data );
4313
+ }
4314
+ catch ( err ) {
4315
+ data = {};
4316
+ }
4317
+
4318
+ this.model.loadPanelsData( data );
4319
+ this.currentData = data;
4320
+ this.toggleWelcomeDisplay();
4321
+ }
4322
+
4323
+ return this;
4324
+ },
4325
+
4326
+ /**
4327
+ * Store the model data in the data html field set in this.setDataField.
4328
+ */
4329
+ storeModelData: function () {
4330
+ var data = JSON.stringify( this.model.get( 'data' ) );
4331
+
4332
+ if ( $( this.dataField ).val() !== data ) {
4333
+ // If the data is different, set it and trigger a content_change event
4334
+ $( this.dataField ).val( data );
4335
+ $( this.dataField ).trigger( 'change' );
4336
+ this.trigger( 'content_change' );
4337
+ }
4338
+ },
4339
+
4340
+ /**
4341
+ * HAndle the visual side of adding a new row to the builder.
4342
+ *
4343
+ * @param row
4344
+ * @param collection
4345
+ * @param options
4346
+ */
4347
+ onAddRow: function ( row, collection, options ) {
4348
+ options = _.extend( { noAnimate: false }, options );
4349
+ // Create a view for the row
4350
+ var rowView = new panels.view.row( { model: row } );
4351
+ rowView.builder = this;
4352
+ rowView.render();
4353
+
4354
+ // Attach the row elements to this builder
4355
+ if ( _.isUndefined( options.at ) || collection.length <= 1 ) {
4356
+ // Insert this at the end of the widgets container
4357
+ rowView.$el.appendTo( this.$( '.so-rows-container' ) );
4358
+ } else {
4359
+ // We need to insert this at a specific position
4360
+ rowView.$el.insertAfter(
4361
+ this.$( '.so-rows-container .so-row-container' ).eq( options.at - 1 )
4362
+ );
4363
+ }
4364
+
4365
+ if ( options.noAnimate === false ) {
4366
+ rowView.visualCreate();
4367
+ }
4368
+
4369
+ this.refreshSortable();
4370
+ rowView.resize();
4371
+ },
4372
+
4373
+ /**
4374
+ * Display the dialog to add a new widget.
4375
+ *
4376
+ * @returns {boolean}
4377
+ */
4378
+ displayAddWidgetDialog: function () {
4379
+ this.dialogs.widgets.openDialog();
4380
+ },
4381
+
4382
+ /**
4383
+ * Display the dialog to add a new row.
4384
+ */
4385
+ displayAddRowDialog: function () {
4386
+ var row = new panels.model.row();
4387
+ var cells = new panels.collection.cells( [ { weight: 0.5 }, { weight: 0.5 } ] );
4388
+ cells.each( function ( cell ) {
4389
+ cell.row = row;
4390
+ } );
4391
+ row.set( 'cells', cells );
4392
+ row.builder = this.model;
4393
+
4394
+ this.dialogs.row.setRowModel( row );
4395
+ this.dialogs.row.openDialog();
4396
+ },
4397
+
4398
+ /**
4399
+ * Display the dialog to add prebuilt layouts.
4400
+ *
4401
+ * @returns {boolean}
4402
+ */
4403
+ displayAddPrebuiltDialog: function () {
4404
+ this.dialogs.prebuilt.openDialog();
4405
+ },
4406
+
4407
+ /**
4408
+ * Display the history dialog.
4409
+ *
4410
+ * @returns {boolean}
4411
+ */
4412
+ displayHistoryDialog: function () {
4413
+ this.dialogs.history.openDialog();
4414
+ },
4415
+
4416
+ /**
4417
+ * Handle pasting a row into the builder.
4418
+ */
4419
+ pasteRowHandler: function () {
4420
+ var pastedModel = panels.helpers.clipboard.getModel( 'row-model' );
4421
+
4422
+ if ( !_.isEmpty( pastedModel ) && pastedModel instanceof panels.model.row ) {
4423
+ this.addHistoryEntry( 'row_pasted' );
4424
+ pastedModel.builder = this.model;
4425
+ this.model.get( 'rows' ).add( pastedModel, {
4426
+ at: this.model.get( 'rows' ).indexOf( this.model ) + 1
4427
+ } );
4428
+ this.model.refreshPanelsData();
4429
+ }
4430
+ },
4431
+
4432
+ /**
4433
+ * Get the model for the currently selected cell
4434
+ */
4435
+ getActiveCell: function ( options ) {
4436
+ options = _.extend( {
4437
+ createCell: true,
4438
+ }, options );
4439
+
4440
+ if ( !this.model.get( 'rows' ).length ) {
4441
+ // There aren't any rows yet
4442
+ if ( options.createCell ) {
4443
+ // Create a row with a single cell
4444
+ this.model.addRow( {}, [ { weight: 1 } ], { noAnimate: true } );
4445
+ } else {
4446
+ return null;
4447
+ }
4448
+ }
4449
+
4450
+ // Make sure the active cell isn't empty, and it's in a row that exists
4451
+ var activeCell = this.activeCell;
4452
+ if ( _.isEmpty( activeCell ) || this.model.get( 'rows' ).indexOf( activeCell.model.row ) === -1 ) {
4453
+ return this.model.get( 'rows' ).last().get( 'cells' ).first();
4454
+ } else {
4455
+ return activeCell.model;
4456
+ }
4457
+ },
4458
+
4459
+ /**
4460
+ * Add a live editor to the builder
4461
+ *
4462
+ * @returns {panels.view.builder}
4463
+ */
4464
+ addLiveEditor: function () {
4465
+ if ( _.isEmpty( this.config.liveEditorPreview ) ) {
4466
+ return this;
4467
+ }
4468
+
4469
+ // Create the live editor and set the builder to this.
4470
+ this.liveEditor = new panels.view.liveEditor( {
4471
+ builder: this,
4472
+ previewUrl: this.config.liveEditorPreview
4473
+ } );
4474
+
4475
+ // Display the live editor button in the toolbar
4476
+ if ( this.liveEditor.hasPreviewUrl() ) {
4477
+ this.$( '.so-builder-toolbar .so-live-editor' ).show();
4478
+ }
4479
+
4480
+ this.trigger( 'builder_live_editor_added' );
4481
+
4482
+ return this;
4483
+ },
4484
+
4485
+ /**
4486
+ * Show the current live editor
4487
+ */
4488
+ displayLiveEditor: function () {
4489
+ if ( _.isUndefined( this.liveEditor ) ) {
4490
+ return;
4491
+ }
4492
+
4493
+ this.liveEditor.open();
4494
+ },
4495
+
4496
+ /**
4497
+ * Add the history browser.
4498
+ *
4499
+ * @return {panels.view.builder}
4500
+ */
4501
+ addHistoryBrowser: function () {
4502
+ if ( _.isEmpty( this.config.liveEditorPreview ) ) {
4503
+ return this;
4504
+ }
4505
+
4506
+ this.dialogs.history = new panels.dialog.history();
4507
+ this.dialogs.history.builder = this;
4508
+ this.dialogs.history.entries.builder = this.model;
4509
+
4510
+ // Set the revert entry
4511
+ this.dialogs.history.setRevertEntry( this.model );
4512
+
4513
+ // Display the live editor button in the toolbar
4514
+ this.$( '.so-builder-toolbar .so-history' ).show();
4515
+ },
4516
+
4517
+ /**
4518
+ * Add an entry.
4519
+ *
4520
+ * @param text
4521
+ * @param data
4522
+ */
4523
+ addHistoryEntry: function ( text, data ) {
4524
+ if ( _.isUndefined( data ) ) {
4525
+ data = null;
4526
+ }
4527
+
4528
+ if ( !_.isUndefined( this.dialogs.history ) ) {
4529
+ this.dialogs.history.entries.addEntry( text, data );
4530
+ }
4531
+ },
4532
+
4533
+ supports: function ( thing ) {
4534
+
4535
+ if ( thing === 'rowAction' ) {
4536
+ // Check if this supports any row action
4537
+ return this.supports( 'addRow' ) || this.supports( 'editRow' ) || this.supports( 'deleteRow' );
4538
+ } else if ( thing === 'widgetAction' ) {
4539
+ // Check if this supports any widget action
4540
+ return this.supports( 'addWidget' ) || this.supports( 'editWidget' ) || this.supports( 'deleteWidget' );
4541
+ }
4542
+
4543
+ return _.isUndefined( this.config.builderSupports[ thing ] ) ? false : this.config.builderSupports[ thing ];
4544
+ },
4545
+
4546
+ /**
4547
+ * Handle a change of the content
4548
+ */
4549
+ handleContentChange: function () {
4550
+
4551
+ // Make sure we actually need to copy content.
4552
+ if ( panelsOptions.copy_content && this.attachedToEditor && this.$el.is( ':visible' ) ) {
4553
+
4554
+ var panelsData = this.model.getPanelsData();
4555
+ if ( !_.isEmpty( panelsData.widgets ) ) {
4556
+ // We're going to create a copy of page builder content into the post content
4557
+ $.post(
4558
+ panelsOptions.ajaxurl,
4559
+ {
4560
+ action: 'so_panels_builder_content',
4561
+ panels_data: JSON.stringify( panelsData ),
4562
+ post_id: this.config.postId
4563
+ },
4564
+ function ( content ) {
4565
+ if ( content !== '' ) {
4566
+ this.updateEditorContent( content );
4567
+ }
4568
+ }.bind( this )
4569
+ );
4570
+ }
4571
+ }
4572
+ },
4573
+
4574
+ /**
4575
+ * Update editor content with the given content.
4576
+ *
4577
+ * @param content
4578
+ */
4579
+ updateEditorContent: function ( content ) {
4580
+ // Switch back to the standard editor
4581
+ if ( this.config.editorType !== 'tinyMCE' || typeof tinyMCE === 'undefined' || _.isNull( tinyMCE.get( "content" ) ) ) {
4582
+ var $editor = $( this.config.editorId );
4583
+ $editor.val( content ).trigger( 'change' ).trigger( 'keyup' );
4584
+ } else {
4585
+ var contentEd = tinyMCE.get( "content" );
4586
+
4587
+ contentEd.setContent( content );
4588
+
4589
+ contentEd.fire( 'change' );
4590
+ contentEd.fire( 'keyup' );
4591
+ }
4592
+
4593
+ this.triggerYoastSeoChange();
4594
+ },
4595
+
4596
+ /**
4597
+ * Trigger a change on Yoast SEO
4598
+ */
4599
+ triggerYoastSeoChange: function () {
4600
+ if ( $( '#yoast_wpseo_focuskw_text_input' ).length ) {
4601
+ var element = document.getElementById( 'yoast_wpseo_focuskw_text_input' ), event;
4602
+
4603
+ if ( document.createEvent ) {
4604
+ event = document.createEvent( "HTMLEvents" );
4605
+ event.initEvent( "keyup", true, true );
4606
+ } else {
4607
+ event = document.createEventObject();
4608
+ event.eventType = "keyup";
4609
+ }
4610
+
4611
+ event.eventName = "keyup";
4612
+
4613
+ if ( document.createEvent ) {
4614
+ element.dispatchEvent( event );
4615
+ } else {
4616
+ element.fireEvent( "on" + event.eventType, event );
4617
+ }
4618
+ }
4619
+ },
4620
+
4621
+ /**
4622
+ * Handle displaying the builder
4623
+ */
4624
+ handleDisplayBuilder: function () {
4625
+ var editor = typeof tinyMCE !== 'undefined' ? tinyMCE.get( 'content' ) : false;
4626
+ var editorContent = ( editor && _.isFunction( editor.getContent ) ) ? editor.getContent() : $( 'textarea#content' ).val();
4627
+
4628
+ if (
4629
+ (
4630
+ _.isEmpty( this.model.get( 'data' ) ) ||
4631
+ ( _.isEmpty( this.model.get( 'data' ).widgets ) && _.isEmpty( this.model.get( 'data' ).grids ) )
4632
+ ) &&
4633
+ editorContent !== ''
4634
+ ) {
4635
+ var editorClass = panelsOptions.text_widget;
4636
+ // There is a small chance a theme will have removed this, so check
4637
+ if ( _.isEmpty( editorClass ) ) {
4638
+ return;
4639
+ }
4640
+
4641
+ // Create the existing page content in a single widget
4642
+ this.model.loadPanelsData( this.model.getPanelsDataFromHtml( editorContent, editorClass ) );
4643
+ this.model.trigger( 'change' );
4644
+ this.model.trigger( 'change:data' );
4645
+ }
4646
+
4647
+ $( '#post-status-info' ).addClass( 'for-siteorigin-panels' );
4648
+ },
4649
+
4650
+ handleHideBuilder: function () {
4651
+ $( '#post-status-info' ).show().removeClass( 'for-siteorigin-panels' );
4652
+ },
4653
+
4654
+ wrapEditorExpandAdjust: function () {
4655
+ try {
4656
+ var events = ( $.hasData( window ) && $._data( window ) ).events.scroll,
4657
+ event;
4658
+
4659
+ for ( var i = 0; i < events.length; i++ ) {
4660
+ if ( events[ i ].namespace === 'editor-expand' ) {
4661
+ event = events[ i ];
4662
+
4663
+ // Wrap the call
4664
+ $( window ).unbind( 'scroll', event.handler );
4665
+ $( window ).bind( 'scroll', function ( e ) {
4666
+ if ( !this.attachedVisible ) {
4667
+ event.handler( e );
4668
+ }
4669
+ }.bind( this ) );
4670
+
4671
+ break;
4672
+ }
4673
+ }
4674
+ }
4675
+ catch ( e ) {
4676
+ // We tried, we failed
4677
+ return;
4678
+ }
4679
+ },
4680
+
4681
+ /**
4682
+ * Either add or remove the narrow class
4683
+ * @returns {exports}
4684
+ */
4685
+ handleBuilderSizing: function () {
4686
+ var width = this.$el.width();
4687
+
4688
+ if ( !width ) {
4689
+ return this;
4690
+ }
4691
+
4692
+ if ( width < 480 ) {
4693
+ this.$el.addClass( 'so-display-narrow' );
4694
+ } else {
4695
+ this.$el.removeClass( 'so-display-narrow' );
4696
+ }
4697
+
4698
+ return this;
4699
+ },
4700
+
4701
+ /**
4702
+ * Set the parent dialog for all the dialogs in this builder.
4703
+ *
4704
+ * @param text
4705
+ * @param dialog
4706
+ */
4707
+ setDialogParents: function ( text, dialog ) {
4708
+ _.each( this.dialogs, function ( p, i, d ) {
4709
+ d[ i ].setParent( text, dialog );
4710
+ } );
4711
+
4712
+ // For any future dialogs
4713
+ this.on( 'add_dialog', function ( newDialog ) {
4714
+ newDialog.setParent( text, dialog );
4715
+ }, this );
4716
+ },
4717
+
4718
+ /**
4719
+ * This shows or hides the welcome display depending on whether there are any rows in the collection.
4720
+ */
4721
+ toggleWelcomeDisplay: function () {
4722
+ if ( !this.model.get( 'rows' ).isEmpty() ) {
4723
+ this.$( '.so-panels-welcome-message' ).hide();
4724
+ } else {
4725
+ this.$( '.so-panels-welcome-message' ).show();
4726
+ }
4727
+ },
4728
+
4729
+ /**
4730
+ * Activate the contextual menu
4731
+ * @param e
4732
+ * @param menu
4733
+ */
4734
+ activateContextMenu: function ( e, menu ) {
4735
+ var builder = this;
4736
+
4737
+ // Of all the visible builders, find the topmost
4738
+ var topmostBuilder = $( '.siteorigin-panels-builder:visible' )
4739
+ .sort( function ( a, b ) {
4740
+ return $( a ).zIndex() > $( b ).zIndex() ? 1 : -1;
4741
+ } )
4742
+ .last();
4743
+
4744
+ var topmostDialog = $( '.so-panels-dialog-wrapper:visible' )
4745
+ .sort( function ( a, b ) {
4746
+ return $( a ).zIndex() > $( b ).zIndex() ? 1 : -1;
4747
+ } )
4748
+ .last();
4749
+
4750
+ var closestDialog = builder.$el.closest( '.so-panels-dialog-wrapper' );
4751
+
4752
+ // Only run this if its element is the topmost builder, in the topmost dialog
4753
+ if (
4754
+ builder.$el.is( topmostBuilder ) &&
4755
+ (
4756
+ topmostDialog.length === 0 ||
4757
+ topmostDialog.is( closestDialog )
4758
+ )
4759
+ ) {
4760
+ // Get the element we're currently hovering over
4761
+ var over = $( [] )
4762
+ .add( builder.$( '.so-panels-welcome-message:visible' ) )
4763
+ .add( builder.$( '.so-rows-container > .so-row-container' ) )
4764
+ .add( builder.$( '.so-cells > .cell' ) )
4765
+ .add( builder.$( '.cell-wrapper > .so-widget' ) )
4766
+ .filter( function ( i ) {
4767
+ return menu.isOverEl( $( this ), e );
4768
+ } );
4769
+
4770
+ var activeView = over.last().data( 'view' );
4771
+ if ( activeView !== undefined && activeView.buildContextualMenu !== undefined ) {
4772
+ // We'll pass this to the current active view so it can popular the contextual menu
4773
+ activeView.buildContextualMenu( e, menu );
4774
+ }
4775
+ else if ( over.last().hasClass( 'so-panels-welcome-message' ) ) {
4776
+ // The user opened the contextual menu on the welcome message
4777
+ this.buildContextualMenu( e, menu );
4778
+ }
4779
+ }
4780
+ },
4781
+
4782
+ /**
4783
+ * Build the contextual menu for the main builder - before any content has been added.
4784
+ */
4785
+ buildContextualMenu: function ( e, menu ) {
4786
+ var actions = {};
4787
+
4788
+ if ( this.supports( 'addRow' ) ) {
4789
+ actions.add_row = { title: panelsOptions.loc.contextual.add_row };
4790
+ }
4791
+
4792
+ if ( panels.helpers.clipboard.canCopyPaste() ) {
4793
+ if ( panels.helpers.clipboard.isModel( 'row-model' ) && this.supports( 'addRow' ) ) {
4794
+ actions.paste_row = { title: panelsOptions.loc.contextual.row_paste };
4795
+ }
4796
+ }
4797
+
4798
+ if ( !_.isEmpty( actions ) ) {
4799
+ menu.addSection(
4800
+ 'builder-actions',
4801
+ {
4802
+ sectionTitle: panelsOptions.loc.contextual.row_actions,
4803
+ search: false,
4804
+ },
4805
+ actions,
4806
+ function ( c ) {
4807
+ switch ( c ) {
4808
+ case 'add_row':
4809
+ this.displayAddRowDialog();
4810
+ break;
4811
+
4812
+ case 'paste_row':
4813
+ this.pasteRowHandler();
4814
+ break;
4815
+ }
4816
+ }.bind( this )
4817
+ );
4818
+ }
4819
+ },
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;
5731
+
5732
+ module.exports = Backbone.View.extend( {
5733
+ template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-live-editor' ).html() ) ),
5734
+
5735
+ previewScrollTop: 0,
5736
+ loadTimes: [],
5737
+ previewFrameId: 1,
5738
+
5739
+ previewUrl: null,
5740
+ previewIframe: null,
5741
+
5742
+ events: {
5743
+ 'click .live-editor-close': 'close',
5744
+ 'click .live-editor-collapse': 'collapse',
5745
+ 'click .live-editor-mode': 'mobileToggle'
5746
+ },
5747
+
5748
+ initialize: function ( options ) {
5749
+ options = _.extend( {
5750
+ builder: false,
5751
+ previewUrl: false,
5752
+ }, options );
5753
+
5754
+ if( _.isEmpty( options.previewUrl ) ) {
5755
+ options.previewUrl = panelsOptions.ajaxurl + "&action=so_panels_live_editor_preview";
5756
+ }
5757
+
5758
+ this.builder = options.builder;
5759
+ this.previewUrl = options.previewUrl;
5760
+
5761
+ this.builder.model.on( 'refresh_panels_data', this.handleRefreshData, this );
5762
+ this.builder.model.on( 'load_panels_data', this.handleLoadData, this );
5763
+ },
5764
+
5765
+ /**
5766
+ * Render the live editor
5767
+ */
5768
+ render: function () {
5769
+ this.setElement( this.template() );
5770
+ this.$el.hide();
5771
+ var thisView = this;
5772
+
5773
+ var isMouseDown = false;
5774
+
5775
+ $( document )
5776
+ .mousedown( function () {
5777
+ isMouseDown = true;
5778
+ } )
5779
+ .mouseup( function () {
5780
+ isMouseDown = false;
5781
+ } );
5782
+
5783
+ // Handle highlighting the relevant widget in the live editor preview
5784
+ this.$el.on( 'mouseenter', '.so-widget-wrapper', function () {
5785
+ var $$ = $( this ),
5786
+ previewWidget = $$.data( 'live-editor-preview-widget' );
5787
+
5788
+ if ( ! isMouseDown && previewWidget !== undefined && previewWidget.length && ! thisView.$( '.so-preview-overlay' ).is( ':visible' ) ) {
5789
+ thisView.highlightElement( previewWidget );
5790
+ thisView.scrollToElement( previewWidget );
5791
+ }
5792
+ } );
5793
+
5794
+ thisView.$el.on( 'mouseleave', '.so-widget-wrapper', function () {
5795
+ thisView.resetHighlights();
5796
+ } );
5797
+
5798
+ thisView.builder.on( 'open_dialog', function () {
5799
+ thisView.resetHighlights();
5800
+ } );
5801
+
5802
+ return this;
5803
+ },
5804
+
5805
+ /**
5806
+ * Attach the live editor to the document
5807
+ */
5808
+ attach: function () {
5809
+ this.$el.appendTo( 'body' );
5810
+ },
5811
+
5812
+ /**
5813
+ * Display the live editor
5814
+ */
5815
+ open: function () {
5816
+ if ( this.$el.html() === '' ) {
5817
+ this.render();
5818
+ }
5819
+ if ( this.$el.closest( 'body' ).length === 0 ) {
5820
+ this.attach();
5821
+ }
5822
+
5823
+ // Disable page scrolling
5824
+ panels.helpers.pageScroll.lock();
5825
+
5826
+ if ( this.$el.is( ':visible' ) ) {
5827
+ return this;
5828
+ }
5829
+
5830
+ // Refresh the preview display
5831
+ this.$el.show();
5832
+ this.refreshPreview( this.builder.model.getPanelsData() );
5833
+
5834
+ // Move the builder view into the Live Editor
5835
+ this.originalContainer = this.builder.$el.parent();
5836
+ this.builder.$el.appendTo( this.$( '.so-live-editor-builder' ) );
5837
+ this.builder.$( '.so-tool-button.so-live-editor' ).hide();
5838
+ this.builder.trigger( 'builder_resize' );
5839
+
5840
+
5841
+ if( $('#original_post_status' ).val() === 'auto-draft' && ! this.autoSaved ) {
5842
+ // The live editor requires a saved draft post, so we'll create one for auto-draft posts
5843
+ var thisView = this;
5844
+
5845
+ if ( wp.autosave ) {
5846
+ // Set a temporary post title so the autosave triggers properly
5847
+ if( $('#title[name="post_title"]' ).val() === '' ) {
5848
+ $('#title[name="post_title"]' ).val( panelsOptions.loc.draft ).trigger('keydown');
5849
+ }
5850
+
5851
+ $( document ).one( 'heartbeat-tick.autosave', function(){
5852
+ thisView.autoSaved = true;
5853
+ thisView.refreshPreview( thisView.builder.model.getPanelsData() );
5854
+ } );
5855
+ wp.autosave.server.triggerSave();
5856
+ }
5857
+ }
5858
+ },
5859
+
5860
+ /**
5861
+ * Close the live editor
5862
+ */
5863
+ close: function () {
5864
+ if ( ! this.$el.is( ':visible' ) ) {
5865
+ return this;
5866
+ }
5867
+
5868
+ this.$el.hide();
5869
+ panels.helpers.pageScroll.unlock();
5870
+
5871
+ // Move the builder back to its original container
5872
+ this.builder.$el.appendTo( this.originalContainer );
5873
+ this.builder.$( '.so-tool-button.so-live-editor' ).show();
5874
+ this.builder.trigger( 'builder_resize' );
5875
+ },
5876
+
5877
+ /**
5878
+ * Collapse the live editor
5879
+ */
5880
+ collapse: function () {
5881
+ this.$el.toggleClass( 'so-collapsed' );
5882
+
5883
+ var text = this.$( '.live-editor-collapse span' );
5884
+ text.html( text.data( this.$el.hasClass( 'so-collapsed' ) ? 'expand' : 'collapse' ) );
5885
+ },
5886
+
5887
+ /**
5888
+ * Create an overlay in the preview.
5889
+ *
5890
+ * @param over
5891
+ * @return {*|Object} The item we're hovering over.
5892
+ */
5893
+ highlightElement: function ( over ) {
5894
+ if( ! _.isUndefined( this.resetHighlightTimeout ) ) {
5895
+ clearTimeout( this.resetHighlightTimeout );
5896
+ }
5897
+
5898
+ // Remove any old overlays
5899
+
5900
+ var body = this.previewIframe.contents().find( 'body' );
5901
+ body.find( '.panel-grid .panel-grid-cell .so-panel' )
5902
+ .filter( function () {
5903
+ // Filter to only include non nested
5904
+ return $( this ).parents( '.so-panel' ).length === 0;
5905
+ } )
5906
+ .not( over )
5907
+ .addClass( 'so-panels-faded' );
5908
+
5909
+ over.removeClass( 'so-panels-faded' ).addClass( 'so-panels-highlighted' );
5910
+ },
5911
+
5912
+ /**
5913
+ * Reset highlights in the live preview
5914
+ */
5915
+ resetHighlights: function() {
5916
+
5917
+ var body = this.previewIframe.contents().find( 'body' );
5918
+ this.resetHighlightTimeout = setTimeout( function(){
5919
+ body.find( '.panel-grid .panel-grid-cell .so-panel' )
5920
+ .removeClass( 'so-panels-faded so-panels-highlighted' );
5921
+ }, 100 );
5922
+ },
5923
+
5924
+ /**
5925
+ * Scroll over an element in the live preview
5926
+ * @param over
5927
+ */
5928
+ scrollToElement: function( over ) {
5929
+ var contentWindow = this.$( '.so-preview iframe' )[0].contentWindow;
5930
+ contentWindow.liveEditorScrollTo( over );
5931
+ },
5932
+
5933
+ handleRefreshData: function ( newData, args ) {
5934
+ if ( ! this.$el.is( ':visible' ) ) {
5935
+ return this;
5936
+ }
5937
+
5938
+ this.refreshPreview( newData );
5939
+ },
5940
+
5941
+ handleLoadData: function () {
5942
+ if ( ! this.$el.is( ':visible' ) ) {
5943
+ return this;
5944
+ }
5945
+
5946
+ this.refreshPreview( this.builder.model.getPanelsData() );
5947
+ },
5948
+
5949
+ /**
5950
+ * Refresh the Live Editor preview.
5951
+ * @returns {exports}
5952
+ */
5953
+ refreshPreview: function ( data ) {
5954
+ var loadTimePrediction = this.loadTimes.length ?
5955
+ _.reduce( this.loadTimes, function ( memo, num ) {
5956
+ return memo + num;
5957
+ }, 0 ) / this.loadTimes.length : 1000;
5958
+
5959
+ // Store the last preview iframe position
5960
+ if( ! _.isNull( this.previewIframe ) ) {
5961
+ if ( ! this.$( '.so-preview-overlay' ).is( ':visible' ) ) {
5962
+ this.previewScrollTop = this.previewIframe.contents().scrollTop();
5963
+ }
5964
+ }
5965
+
5966
+ // Add a loading bar
5967
+ this.$( '.so-preview-overlay' ).show();
5968
+ this.$( '.so-preview-overlay .so-loading-bar' )
5969
+ .clearQueue()
5970
+ .css( 'width', '0%' )
5971
+ .animate( {width: '100%'}, parseInt( loadTimePrediction ) + 100 );
5972
+
5973
+
5974
+ this.postToIframe(
5975
+ {
5976
+ live_editor_panels_data: JSON.stringify( data ),
5977
+ live_editor_post_ID: this.builder.config.postId
5978
+ },
5979
+ this.previewUrl,
5980
+ this.$('.so-preview')
5981
+ );
5982
+
5983
+ this.previewIframe.data( 'load-start', new Date().getTime() );
5984
+ },
5985
+
5986
+ /**
5987
+ * Use a temporary form to post data to an iframe.
5988
+ *
5989
+ * @param data The data to send
5990
+ * @param url The preview URL
5991
+ * @param target The target iframe
5992
+ */
5993
+ postToIframe: function( data, url, target ){
5994
+ // Store the old preview
5995
+
5996
+ if( ! _.isNull( this.previewIframe ) ) {
5997
+ this.previewIframe.remove();
5998
+ }
5999
+
6000
+ var iframeId = 'siteorigin-panels-live-preview-' + this.previewFrameId;
6001
+
6002
+ // Remove the old preview frame
6003
+ this.previewIframe = $('<iframe src="javascript:false;" />')
6004
+ .attr( {
6005
+ 'id' : iframeId,
6006
+ 'name' : iframeId,
6007
+ } )
6008
+ .appendTo( target )
6009
+
6010
+ this.setupPreviewFrame( this.previewIframe );
6011
+
6012
+ // We can use a normal POST form submit
6013
+ var tempForm = $('<form id="soPostToPreviewFrame" method="post" />')
6014
+ .attr( {
6015
+ id: iframeId,
6016
+ target: this.previewIframe.attr('id'),
6017
+ action: url
6018
+ } )
6019
+ .appendTo( 'body' );
6020
+
6021
+ $.each( data, function( name, value ){
6022
+ $('<input type="hidden" />')
6023
+ .attr( {
6024
+ name: name,
6025
+ value: value
6026
+ } )
6027
+ .appendTo( tempForm );
6028
+ } );
6029
+
6030
+ tempForm
6031
+ .submit()
6032
+ .remove();
6033
+
6034
+ this.previewFrameId++;
6035
+
6036
+ return this.previewIframe;
6037
+ },
6038
+
6039
+ /**
6040
+ * Do all the basic setup for the preview Iframe element
6041
+ * @param iframe
6042
+ */
6043
+ setupPreviewFrame: function( iframe ){
6044
+ var thisView = this;
6045
+ iframe
6046
+ .data( 'iframeready', false )
6047
+ .on( 'iframeready', function () {
6048
+ var $$ = $( this ),
6049
+ $iframeContents = $$.contents();
6050
+
6051
+ if( $$.data( 'iframeready' ) ) {
6052
+ // Skip this if the iframeready function has already run
6053
+ return;
6054
+ }
6055
+
6056
+ $$.data( 'iframeready', true );
6057
+
6058
+ if ( $$.data( 'load-start' ) !== undefined ) {
6059
+ thisView.loadTimes.unshift( new Date().getTime() - $$.data( 'load-start' ) );
6060
+
6061
+ if ( ! _.isEmpty( thisView.loadTimes ) ) {
6062
+ thisView.loadTimes = thisView.loadTimes.slice( 0, 4 );
6063
+ }
6064
+ }
6065
+
6066
+ setTimeout( function(){
6067
+ // Scroll to the correct position
6068
+ $iframeContents.scrollTop( thisView.previewScrollTop );
6069
+ thisView.$( '.so-preview-overlay' ).hide();
6070
+ }, 100 );
6071
+
6072
+
6073
+ // Lets find all the first level grids. This is to account for the Page Builder layout widget.
6074
+ var layoutWrapper = $iframeContents.find( '#pl-' + thisView.builder.config.postId );
6075
+ layoutWrapper.find( '.panel-grid .panel-grid-cell .so-panel' )
6076
+ .filter( function () {
6077
+ // Filter to only include non nested
6078
+ return $( this ).closest( '.panel-layout' ).is( layoutWrapper );
6079
+ } )
6080
+ .each( function ( i, el ) {
6081
+ var $$ = $( el );
6082
+ var widgetEdit = thisView.$( '.so-live-editor-builder .so-widget-wrapper' ).eq( $$.data( 'index' ) );
6083
+ widgetEdit.data( 'live-editor-preview-widget', $$ );
6084
+
6085
+ $$
6086
+ .css( {
6087
+ 'cursor': 'pointer'
6088
+ } )
6089
+ .mouseenter( function () {
6090
+ widgetEdit.parent().addClass( 'so-hovered' );
6091
+ thisView.highlightElement( $$ );
6092
+ } )
6093
+ .mouseleave( function () {
6094
+ widgetEdit.parent().removeClass( 'so-hovered' );
6095
+ thisView.resetHighlights();
6096
+ } )
6097
+ .click( function ( e ) {
6098
+ e.preventDefault();
6099
+ // When we click a widget, send that click to the form
6100
+ widgetEdit.find( '.title h4' ).click();
6101
+ } );
6102
+ } );
6103
+
6104
+ // Prevent default clicks inside the preview iframe
6105
+ $iframeContents.find( "a" ).css( {'pointer-events': 'none'} ).click( function ( e ) {
6106
+ e.preventDefault();
6107
+ } );
6108
+
6109
+ } )
6110
+ .on( 'load', function(){
6111
+ var $$ = $( this );
6112
+ if( ! $$.data( 'iframeready' ) ) {
6113
+ $$.trigger('iframeready');
6114
+ }
6115
+ } );
6116
+ },
6117
+
6118
+ /**
6119
+ * Return true if the live editor has a valid preview URL.
6120
+ * @return {boolean}
6121
+ */
6122
+ hasPreviewUrl: function () {
6123
+ return this.$( 'form.live-editor-form' ).attr( 'action' ) !== '';
6124
+ },
6125
+
6126
+ /**
6127
+ * Toggle the size of the preview iframe to simulate mobile devices.
6128
+ * @param e
6129
+ */
6130
+ mobileToggle: function( e ){
6131
+ var button = $( e.currentTarget );
6132
+ this.$('.live-editor-mode' ).not( button ).removeClass('so-active');
6133
+ button.addClass( 'so-active' );
6134
+
6135
+ this.$el
6136
+ .removeClass( 'live-editor-desktop-mode live-editor-tablet-mode live-editor-mobile-mode' )
6137
+ .addClass( 'live-editor-' + button.data( 'mode' ) + '-mode' );
6138
+
6139
+ }
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;
6555
+
6556
+ module.exports = Backbone.View.extend( {
6557
+
6558
+ stylesLoaded: false,
6559
+
6560
+ initialize: function () {
6561
+
6562
+ },
6563
+
6564
+ /**
6565
+ * Render the visual styles object.
6566
+ *
6567
+ * @param type
6568
+ * @param postId
6569
+ */
6570
+ render: function ( stylesType, postId, args ) {
6571
+ if ( _.isUndefined( stylesType ) ) {
6572
+ return;
6573
+ }
6574
+
6575
+ // Add in the default args
6576
+ args = _.extend( {
6577
+ builderType: '',
6578
+ dialog: null
6579
+ }, args );
6580
+
6581
+ this.$el.addClass( 'so-visual-styles so-' + stylesType + '-styles' );
6582
+
6583
+ var postArgs = {
6584
+ builderType: args.builderType
6585
+ };
6586
+
6587
+ if ( stylesType === 'cell') {
6588
+ postArgs.index = args.index;
6589
+ }
6590
+
6591
+ // Load the form
6592
+ $.post(
6593
+ panelsOptions.ajaxurl,
6594
+ {
6595
+ action: 'so_panels_style_form',
6596
+ type: stylesType,
6597
+ style: this.model.get( 'style' ),
6598
+ args: JSON.stringify( postArgs ),
6599
+ postId: postId
6600
+ },
6601
+ function ( response ) {
6602
+ this.$el.html( response );
6603
+ this.setupFields();
6604
+ this.stylesLoaded = true;
6605
+ this.trigger( 'styles_loaded', ! _.isEmpty( response ) );
6606
+ if ( ! _.isNull( args.dialog ) ) {
6607
+ args.dialog.trigger( 'styles_loaded', ! _.isEmpty( response ) );
6608
+ }
6609
+ }.bind(this)
6610
+ );
6611
+
6612
+ return this;
6613
+ },
6614
+
6615
+ /**
6616
+ * Attach the style view to the DOM.
6617
+ *
6618
+ * @param wrapper
6619
+ */
6620
+ attach: function ( wrapper ) {
6621
+ wrapper.append( this.$el );
6622
+ },
6623
+
6624
+ /**
6625
+ * Detach the styles view from the DOM
6626
+ */
6627
+ detach: function () {
6628
+ this.$el.detach();
6629
+ },
6630
+
6631
+ /**
6632
+ * Setup all the fields
6633
+ */
6634
+ setupFields: function () {
6635
+
6636
+ // Set up the sections as collapsible
6637
+ this.$( '.style-section-wrapper' ).each( function () {
6638
+ var $s = $( this );
6639
+
6640
+ $s.find( '.style-section-head' ).click( function ( e ) {
6641
+ e.preventDefault();
6642
+ $s.find( '.style-section-fields' ).slideToggle( 'fast' );
6643
+ } );
6644
+ } );
6645
+
6646
+ // Set up the color fields
6647
+ if ( ! _.isUndefined( $.fn.wpColorPicker ) ) {
6648
+ if ( _.isObject( panelsOptions.wpColorPickerOptions.palettes ) && ! $.isArray( panelsOptions.wpColorPickerOptions.palettes ) ) {
6649
+ panelsOptions.wpColorPickerOptions.palettes = $.map( panelsOptions.wpColorPickerOptions.palettes, function ( el ) {
6650
+ return el;
6651
+ } );
6652
+ }
6653
+ this.$( '.so-wp-color-field' ).wpColorPicker( panelsOptions.wpColorPickerOptions );
6654
+ }
6655
+
6656
+ // Set up the image select fields
6657
+ this.$( '.style-field-image' ).each( function () {
6658
+ var frame = null;
6659
+ var $s = $( this );
6660
+
6661
+ $s.find( '.so-image-selector' ).click( function ( e ) {
6662
+ e.preventDefault();
6663
+
6664
+ if ( frame === null ) {
6665
+ // Create the media frame.
6666
+ frame = wp.media( {
6667
+ // Set the title of the modal.
6668
+ title: 'choose',
6669
+
6670
+ // Tell the modal to show only images.
6671
+ library: {
6672
+ type: 'image'
6673
+ },
6674
+
6675
+ // Customize the submit button.
6676
+ button: {
6677
+ // Set the text of the button.
6678
+ text: 'Done',
6679
+ close: true
6680
+ }
6681
+ } );
6682
+
6683
+ frame.on( 'select', function () {
6684
+ var attachment = frame.state().get( 'selection' ).first().attributes;
6685
+
6686
+ var url = attachment.url;
6687
+ if ( ! _.isUndefined( attachment.sizes ) ) {
6688
+ try {
6689
+ url = attachment.sizes.thumbnail.url;
6690
+ }
6691
+ catch ( e ) {
6692
+ // We'll use the full image instead
6693
+ url = attachment.sizes.full.url;
6694
+ }
6695
+ }
6696
+ $s.find( '.current-image' ).css( 'background-image', 'url(' + url + ')' );
6697
+
6698
+ // Store the ID
6699
+ $s.find( 'input' ).val( attachment.id )
6700
+ } );
6701
+ }
6702
+
6703
+ frame.open();
6704
+
6705
+ } );
6706
+
6707
+ // Handle clicking on remove
6708
+ $s.find( '.remove-image' ).click( function ( e ) {
6709
+ e.preventDefault();
6710
+ $s.find( '.current-image' ).css( 'background-image', 'none' );
6711
+ $s.find( 'input' ).val( '' );
6712
+ } );
6713
+ } );
6714
+
6715
+ // Set up all the measurement fields
6716
+ this.$( '.style-field-measurement' ).each( function () {
6717
+ var $$ = $( this );
6718
+
6719
+ var text = $$.find( 'input[type="text"]' );
6720
+ var unit = $$.find( 'select' );
6721
+ var hidden = $$.find( 'input[type="hidden"]' );
6722
+
6723
+ text.focus( function(){
6724
+ $(this).select();
6725
+ } );
6726
+
6727
+ /**
6728
+ * Load value into the visible input fields.
6729
+ * @param value
6730
+ */
6731
+ var loadValue = function( value ) {
6732
+ if( value === '' ) {
6733
+ return;
6734
+ }
6735
+
6736
+ var re = /(?:([0-9\.,\-]+)(.*))+/;
6737
+ var valueList = hidden.val().split( ' ' );
6738
+ var valueListValue = [];
6739
+ for ( var i in valueList ) {
6740
+ var match = re.exec( valueList[i] );
6741
+ if ( ! _.isNull( match ) && ! _.isUndefined( match[1] ) && ! _.isUndefined( match[2] ) ) {
6742
+ valueListValue.push( match[1] );
6743
+ unit.val( match[2] );
6744
+ }
6745
+ }
6746
+
6747
+ if( text.length === 1 ) {
6748
+ // This is a single input text field
6749
+ text.val( valueListValue.join( ' ' ) );
6750
+ }
6751
+ else {
6752
+ // We're dealing with a multiple field
6753
+ if( valueListValue.length === 1 ) {
6754
+ valueListValue = [ valueListValue[0], valueListValue[0], valueListValue[0], valueListValue[0] ];
6755
+ }
6756
+ else if( valueListValue.length === 2 ) {
6757
+ valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[0], valueListValue[1] ];
6758
+ }
6759
+ else if( valueListValue.length === 3 ) {
6760
+ valueListValue = [ valueListValue[0], valueListValue[1], valueListValue[2], valueListValue[1] ];
6761
+ }
6762
+
6763
+ // Store this in the visible fields
6764
+ text.each( function( i, el ) {
6765
+ $( el ).val( valueListValue[i] );
6766
+ } );
6767
+ }
6768
+ };
6769
+ loadValue( hidden.val() );
6770
+
6771
+ /**
6772
+ * Set value of the hidden field based on inputs
6773
+ */
6774
+ var setValue = function( e ){
6775
+ var i;
6776
+
6777
+ if( text.length === 1 ) {
6778
+ // We're dealing with a single measurement
6779
+ var fullString = text
6780
+ .val()
6781
+ .split( ' ' )
6782
+ .filter( function ( value ) {
6783
+ return value !== '';
6784
+ } )
6785
+ .map( function ( value ) {
6786
+ return value + unit.val();
6787
+ } )
6788
+ .join( ' ' );
6789
+ hidden.val( fullString );
6790
+ }
6791
+ else {
6792
+ var target = $( e.target ),
6793
+ valueList = [],
6794
+ emptyIndex = [],
6795
+ fullIndex = [];
6796
+
6797
+ text.each( function( i, el ) {
6798
+ var value = $( el ).val( ) !== '' ? parseFloat( $( el ).val( ) ) : null;
6799
+ valueList.push( value );
6800
+
6801
+ if( value === null ) {
6802
+ emptyIndex.push( i );
6803
+ }
6804
+ else {
6805
+ fullIndex.push( i );
6806
+ }
6807
+ } );
6808
+
6809
+ if( emptyIndex.length === 3 && fullIndex[0] === text.index( target ) ) {
6810
+ text.val( target.val() );
6811
+ valueList = [ target.val(), target.val(), target.val(), target.val() ];
6812
+ }
6813
+
6814
+ if( JSON.stringify( valueList ) === JSON.stringify( [ null, null, null, null ] ) ) {
6815
+ hidden.val('');
6816
+ }
6817
+ else {
6818
+ hidden.val( valueList.map( function( k ){
6819
+ return ( k === null ? 0 : k ) + unit.val();
6820
+ } ).join( ' ' ) );
6821
+ }
6822
+ }
6823
+ };
6824
+
6825
+ // Set the value when ever anything changes
6826
+ text.change( setValue );
6827
+ unit.change( setValue );
6828
+ } );
6829
+ }
6830
+
6831
+ } );
6832
+
6833
+ },{}],29:[function(require,module,exports){
6834
+ var panels = window.panels, $ = jQuery;
6835
+
6836
+ module.exports = Backbone.View.extend( {
6837
+ template: _.template( panels.helpers.utils.processTemplate( $( '#siteorigin-panels-builder-widget' ).html() ) ),
6838
+
6839
+ // The cell view that this widget belongs to
6840
+ cell: null,
6841
+
6842
+ // The edit dialog
6843
+ dialog: null,
6844
+
6845
+ events: {
6846
+ 'click .widget-edit': 'editHandler',
6847
+ 'click .title h4': 'titleClickHandler',
6848
+ 'click .actions .widget-duplicate': 'duplicateHandler',
6849
+ 'click .actions .widget-delete': 'deleteHandler'
6850
+ },
6851
+
6852
+ /**
6853
+ * Initialize the widget
6854
+ */
6855
+ initialize: function () {
6856
+ this.model.on( 'user_edit', this.editHandler, this ); // When a user wants to edit the widget model
6857
+ this.model.on( 'user_duplicate', this.duplicateHandler, this ); // When a user wants to duplicate the widget model
6858
+ this.model.on( 'destroy', this.onModelDestroy, this );
6859
+ this.model.on( 'visual_destroy', this.visualDestroyModel, this );
6860
+
6861
+ this.model.on( 'change:values', this.onModelChange, this );
6862
+ this.model.on( 'change:label', this.onLabelChange, this );
6863
+ },
6864
+
6865
+ /**
6866
+ * Render the widget
6867
+ */
6868
+ render: function ( options ) {
6869
+ options = _.extend( {'loadForm': false}, options );
6870
+
6871
+ this.setElement( this.template( {
6872
+ title: this.model.getWidgetField( 'title' ),
6873
+ description: this.model.getTitle()
6874
+ } ) );
6875
+
6876
+ this.$el.data( 'view', this );
6877
+
6878
+ // Remove any unsupported actions
6879
+ if( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
6880
+ this.$( '.actions .widget-edit' ).remove();
6881
+ this.$el.addClass('so-widget-no-edit');
6882
+ }
6883
+ if( ! this.cell.row.builder.supports( 'addWidget' ) ) {
6884
+ this.$( '.actions .widget-duplicate' ).remove();
6885
+ this.$el.addClass('so-widget-no-duplicate');
6886
+ }
6887
+ if( ! this.cell.row.builder.supports( 'deleteWidget' ) ) {
6888
+ this.$( '.actions .widget-delete' ).remove();
6889
+ this.$el.addClass('so-widget-no-delete');
6890
+ }
6891
+ if( ! this.cell.row.builder.supports( 'moveWidget' ) ) {
6892
+ this.$el.addClass('so-widget-no-move');
6893
+ }
6894
+ if( !$.trim( this.$('.actions').html() ).length ) {
6895
+ this.$( '.actions' ).remove();
6896
+ }
6897
+
6898
+ if( this.model.get( 'read_only' ) ) {
6899
+ this.$el.addClass('so-widget-read-only');
6900
+ }
6901
+
6902
+ if ( _.size( this.model.get( 'values' ) ) === 0 || options.loadForm ) {
6903
+ // If this widget doesn't have a value, create a form and save it
6904
+ var dialog = this.getEditDialog();
6905
+
6906
+ // Save the widget as soon as the form is loaded
6907
+ dialog.once( 'form_loaded', dialog.saveWidget, dialog );
6908
+
6909
+ // Setup the dialog to load the form
6910
+ dialog.setupDialog();
6911
+ }
6912
+
6913
+ return this;
6914
+ },
6915
+
6916
+ /**
6917
+ * Display an animation that implies creation using a visual animation
6918
+ */
6919
+ visualCreate: function () {
6920
+ this.$el.hide().fadeIn( 'fast' );
6921
+ },
6922
+
6923
+ /**
6924
+ * Get the dialog view of the form that edits this widget
6925
+ *
6926
+ * @returns {null}
6927
+ */
6928
+ getEditDialog: function () {
6929
+ if ( this.dialog === null ) {
6930
+ this.dialog = new panels.dialog.widget( {
6931
+ model: this.model
6932
+ } );
6933
+ this.dialog.setBuilder( this.cell.row.builder );
6934
+
6935
+ // Store the widget view
6936
+ this.dialog.widgetView = this;
6937
+ }
6938
+ return this.dialog;
6939
+ },
6940
+
6941
+ /**
6942
+ * Handle clicking on edit widget.
6943
+ *
6944
+ * @returns {boolean}
6945
+ */
6946
+ editHandler: function () {
6947
+ // Create a new dialog for editing this
6948
+ this.getEditDialog().openDialog();
6949
+ },
6950
+
6951
+ titleClickHandler: function( event ){
6952
+ if ( ! this.cell.row.builder.supports( 'editWidget' ) || this.model.get( 'read_only' ) ) {
6953
+ return this;
6954
+ }
6955
+ this.editHandler();
6956
+ return this;
6957
+ },
6958
+
6959
+ /**
6960
+ * Handle clicking on duplicate.
6961
+ *
6962
+ * @returns {boolean}
6963
+ */
6964
+ duplicateHandler: function () {
6965
+ // Add the history entry
6966
+ this.cell.row.builder.addHistoryEntry( 'widget_duplicated' );
6967
+
6968
+ // Create the new widget and connect it to the widget collection for the current row
6969
+ var newWidget = this.model.clone( this.model.cell );
6970
+
6971
+ this.cell.model.get('widgets').add( newWidget, {
6972
+ // Add this after the existing model
6973
+ at: this.model.collection.indexOf( this.model ) + 1
6974
+ } );
6975
+
6976
+ this.cell.row.builder.model.refreshPanelsData();
6977
+ return this;
6978
+ },
6979
+
6980
+ /**
6981
+ * Copy the row to a cookie based clipboard
6982
+ */
6983
+ copyHandler: function(){
6984
+ panels.helpers.clipboard.setModel( this.model );
6985
+ },
6986
+
6987
+ /**
6988
+ * Handle clicking on delete.
6989
+ *
6990
+ * @returns {boolean}
6991
+ */
6992
+ deleteHandler: function () {
6993
+ this.model.trigger( 'visual_destroy' );
6994
+ return this;
6995
+ },
6996
+
6997
+ onModelChange: function () {
6998
+ // Update the description when ever the model changes
6999
+ this.$( '.description' ).html( this.model.getTitle() );
7000
+ },
7001
+
7002
+ onLabelChange: function( model ) {
7003
+ this.$( '.title > h4' ).text( model.getWidgetField( 'title' ) );
7004
+ },
7005
+
7006
+ /**
7007
+ * When the model is destroyed, fade it out
7008
+ */
7009
+ onModelDestroy: function () {
7010
+ this.remove();
7011
+ },
7012
+
7013
+ /**
7014
+ * Visually destroy a model
7015
+ */
7016
+ visualDestroyModel: function () {
7017
+ // Add the history entry
7018
+ this.cell.row.builder.addHistoryEntry( 'widget_deleted' );
7019
+
7020
+ var thisView = this;
7021
+ this.$el.fadeOut( 'fast', function () {
7022
+ thisView.cell.row.resize();
7023
+ thisView.model.destroy();
7024
+ thisView.cell.row.builder.model.refreshPanelsData();
7025
+ thisView.remove();
7026
+ } );
7027
+
7028
+ return this;
7029
+ },
7030
+
7031
+ /**
7032
+ * Build up the contextual menu for a widget
7033
+ *
7034
+ * @param e
7035
+ * @param menu
7036
+ */
7037
+ buildContextualMenu: function ( e, menu ) {
7038
+ if( this.cell.row.builder.supports( 'addWidget' ) ) {
7039
+ menu.addSection(
7040
+ 'add-widget-below',
7041
+ {
7042
+ sectionTitle: panelsOptions.loc.contextual.add_widget_below,
7043
+ searchPlaceholder: panelsOptions.loc.contextual.search_widgets,
7044
+ defaultDisplay: panelsOptions.contextual.default_widgets
7045
+ },
7046
+ panelsOptions.widgets,
7047
+ function ( c ) {
7048
+ this.cell.row.builder.addHistoryEntry( 'widget_added' );
7049
+
7050
+ var widget = new panels.model.widget( {
7051
+ class: c
7052
+ } );
7053
+ widget.cell = this.cell.model;
7054
+
7055
+ // Insert the new widget below
7056
+ this.cell.model.get('widgets').add( widget, {
7057
+ // Add this after the existing model
7058
+ at: this.model.collection.indexOf( this.model ) + 1
7059
+ } );
7060
+
7061
+ this.cell.row.builder.model.refreshPanelsData();
7062
+ }.bind( this )
7063
+ );
7064
+ }
7065
+
7066
+ var actions = {};
7067
+
7068
+ if( this.cell.row.builder.supports( 'editWidget' ) && ! this.model.get( 'read_only' ) ) {
7069
+ actions.edit = { title: panelsOptions.loc.contextual.widget_edit };
7070
+ }
7071
+
7072
+ // Copy and paste functions
7073
+ if ( panels.helpers.clipboard.canCopyPaste() ) {
7074
+ actions.copy = {title: panelsOptions.loc.contextual.widget_copy};
7075
+ }
7076
+
7077
+ if( this.cell.row.builder.supports( 'addWidget' ) ) {
7078
+ actions.duplicate = { title: panelsOptions.loc.contextual.widget_duplicate };
7079
+ }
7080
+
7081
+ if( this.cell.row.builder.supports( 'deleteWidget' ) ) {
7082
+ actions.delete = { title: panelsOptions.loc.contextual.widget_delete, confirm: true };
7083
+ }
7084
+
7085
+ if( ! _.isEmpty( actions ) ) {
7086
+ menu.addSection(
7087
+ 'widget-actions',
7088
+ {
7089
+ sectionTitle: panelsOptions.loc.contextual.widget_actions,
7090
+ search: false,
7091
+ },
7092
+ actions,
7093
+ function ( c ) {
7094
+ switch ( c ) {
7095
+ case 'edit':
7096
+ this.editHandler();
7097
+ break;
7098
+ case 'copy':
7099
+ this.copyHandler();
7100
+ break;
7101
+ case 'duplicate':
7102
+ this.duplicateHandler();
7103
+ break;
7104
+ case 'delete':
7105
+ this.visualDestroyModel();
7106
+ break;
7107
+ }
7108
+ }.bind( this )
7109
+ );
7110
+ }
7111
+
7112
+ // Lets also add the contextual menu for the entire row
7113
+ this.cell.buildContextualMenu( e, menu );
7114
+ }
7115
+
7116
+ } );
7117
+
7118
+ },{}],30:[function(require,module,exports){
7119
+ var $ = jQuery;
7120
+
7121
+ var customHtmlWidget = {
7122
+ addWidget: function( idBase, widgetContainer, widgetId ) {
7123
+ var component = wp.customHtmlWidgets;
7124
+
7125
+ var fieldContainer = $( '<div></div>' );
7126
+ var syncContainer = widgetContainer.find( '.widget-content:first' );
7127
+ syncContainer.before( fieldContainer );
7128
+
7129
+ var widgetControl = new component.CustomHtmlWidgetControl( {
7130
+ el: fieldContainer,
7131
+ syncContainer: syncContainer,
7132
+ } );
7133
+
7134
+ widgetControl.initializeEditor();
7135
+
7136
+ // HACK: To ensure CodeMirror resize for the gutter.
7137
+ widgetControl.editor.codemirror.refresh();
7138
+
7139
+ return widgetControl;
7140
+ }
7141
+ };
7142
+
7143
+ module.exports = customHtmlWidget;
7144
+
7145
+ },{}],31:[function(require,module,exports){
7146
+ var customHtmlWidget = require( './custom-html-widget' );
7147
+ var mediaWidget = require( './media-widget' );
7148
+ var textWidget = require( './text-widget' );
7149
+
7150
+ var jsWidget = {
7151
+ CUSTOM_HTML: 'custom_html',
7152
+ MEDIA_AUDIO: 'media_audio',
7153
+ MEDIA_GALLERY: 'media_gallery',
7154
+ MEDIA_IMAGE: 'media_image',
7155
+ MEDIA_VIDEO: 'media_video',
7156
+ TEXT: 'text',
7157
+
7158
+ addWidget: function( widgetContainer, widgetId ) {
7159
+ var idBase = widgetContainer.find( '> .id_base' ).val();
7160
+ var widget;
7161
+
7162
+ switch ( idBase ) {
7163
+ case this.CUSTOM_HTML:
7164
+ widget = customHtmlWidget;
7165
+ break;
7166
+ case this.MEDIA_AUDIO:
7167
+ case this.MEDIA_GALLERY:
7168
+ case this.MEDIA_IMAGE:
7169
+ case this.MEDIA_VIDEO:
7170
+ widget = mediaWidget;
7171
+ break;
7172
+ case this.TEXT:
7173
+ widget = textWidget;
7174
+ break
7175
+ }
7176
+
7177
+ widget.addWidget( idBase, widgetContainer, widgetId );
7178
+ },
7179
+ };
7180
+
7181
+ module.exports = jsWidget;
7182
+
7183
+ },{"./custom-html-widget":30,"./media-widget":32,"./text-widget":33}],32:[function(require,module,exports){
7184
+ var $ = jQuery;
7185
+
7186
+ var mediaWidget = {
7187
+ addWidget: function( idBase, widgetContainer, widgetId ) {
7188
+ var component = wp.mediaWidgets;
7189
+
7190
+ var ControlConstructor = component.controlConstructors[ idBase ];
7191
+ if ( ! ControlConstructor ) {
7192
+ return;
7193
+ }
7194
+
7195
+ var ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel;
7196
+ var syncContainer = widgetContainer.find( '> .widget-content' );
7197
+ var controlContainer = $( '<div class="media-widget-control"></div>' );
7198
+ syncContainer.before( controlContainer );
7199
+
7200
+ var modelAttributes = {};
7201
+ syncContainer.find( '.media-widget-instance-property' ).each( function() {
7202
+ var input = $( this );
7203
+ modelAttributes[ input.data( 'property' ) ] = input.val();
7204
+ });
7205
+ modelAttributes.widget_id = widgetId;
7206
+
7207
+ var widgetModel = new ModelConstructor( modelAttributes );
7208
+
7209
+ var widgetControl = new ControlConstructor({
7210
+ el: controlContainer,
7211
+ syncContainer: syncContainer,
7212
+ model: widgetModel,
7213
+ });
7214
+
7215
+ widgetControl.render();
7216
+
7217
+ return widgetControl;
7218
+ }
7219
+ };
7220
+
7221
+ module.exports = mediaWidget;
7222
+
7223
+ },{}],33:[function(require,module,exports){
7224
+ var $ = jQuery;
7225
+
7226
+ var textWidget = {
7227
+ addWidget: function( idBase, widgetContainer, widgetId ) {
7228
+ var component = wp.textWidgets;
7229
+
7230
+ var options = {};
7231
+ var visualField = widgetContainer.find( '.visual' );
7232
+ // 'visual' field and syncContainer were introduced together in 4.8.1
7233
+ if ( visualField.length > 0 ) {
7234
+ // If 'visual' field has no value it's a legacy text widget.
7235
+ if ( ! visualField.val() ) {
7236
+ return null;
7237
+ }
7238
+
7239
+ var fieldContainer = $( '<div></div>' );
7240
+ var syncContainer = widgetContainer.find( '.widget-content:first' );
7241
+ syncContainer.before( fieldContainer );
7242
+
7243
+ options = {
7244
+ el: fieldContainer,
7245
+ syncContainer: syncContainer,
7246
+ };
7247
+ } else {
7248
+ options = { el: widgetContainer };
7249
+ }
7250
+
7251
+ var widgetControl = new component.TextWidgetControl( options );
7252
+
7253
+ widgetControl.initializeEditor();
7254
+
7255
+ return widgetControl;
7256
+ }
7257
+ };
7258
+
7259
+ module.exports = textWidget;
7260
+
7261
+ },{}]},{},[16]);
js/siteorigin-panels-264.min.js ADDED
@@ -0,0 +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("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-264.js ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global _, jQuery */
2
+
3
+ jQuery( function ( $ ) {
4
+
5
+ var fullContainer = $( panelsStyles.fullContainer );
6
+ if ( fullContainer.length === 0 ) {
7
+ fullContainer = $( 'body' );
8
+ }
9
+
10
+ // Stretch all the full width rows
11
+ var stretchFullWidthRows = function () {
12
+
13
+ $( '.siteorigin-panels-stretch.panel-row-style' ).each( function () {
14
+ var $$ = $( this );
15
+
16
+ // Reset all the styles associated with row stretching
17
+ $$.css( {
18
+ 'margin-left': 0,
19
+ 'margin-right': 0,
20
+ 'padding-left': 0,
21
+ 'padding-right': 0
22
+ } );
23
+
24
+ var leftSpace = $$.offset().left - fullContainer.offset().left,
25
+ rightSpace = fullContainer.outerWidth() - leftSpace - $$.parent().outerWidth();
26
+
27
+ $$.css( {
28
+ 'margin-left': - leftSpace,
29
+ 'margin-right': - rightSpace,
30
+ 'padding-left': $$.data( 'stretch-type' ) === 'full' ? leftSpace : 0,
31
+ 'padding-right': $$.data( 'stretch-type' ) === 'full' ? rightSpace : 0
32
+ } );
33
+
34
+ var cells = $$.find( '> .panel-grid-cell' );
35
+
36
+ if ( $$.data( 'stretch-type' ) === 'full-stretched' && cells.length === 1 ) {
37
+ cells.css( {
38
+ 'padding-left': 0,
39
+ 'padding-right': 0
40
+ } );
41
+ }
42
+
43
+ $$.css( {
44
+ 'border-left': 0,
45
+ 'border-right': 0
46
+ } );
47
+ } );
48
+
49
+ if ( $( '.siteorigin-panels-stretch.panel-row-style' ).length ) {
50
+ $( window ).trigger( 'panelsStretchRows' );
51
+ }
52
+ }
53
+ $( window ).on( 'resize load', stretchFullWidthRows );
54
+ stretchFullWidthRows();
55
+
56
+ // This should have been done in the footer, but run it here just incase.
57
+ $( 'body' ).removeClass( 'siteorigin-panels-before-js' );
58
+
59
+ } );
js/styling-264.min.js ADDED
@@ -0,0 +1 @@
 
1
+ jQuery(function(t){var e=t(panelsStyles.fullContainer);0===e.length&&(e=t("body"));var r=function(){t(".siteorigin-panels-stretch.panel-row-style").each(function(){var r=t(this);r.css({"margin-left":0,"margin-right":0,"padding-left":0,"padding-right":0});var i=r.offset().left-e.offset().left,n=e.outerWidth()-i-r.parent().outerWidth();r.css({"margin-left":-i,"margin-right":-n,"padding-left":"full"===r.data("stretch-type")?i:0,"padding-right":"full"===r.data("stretch-type")?n:0});var a=r.find("> .panel-grid-cell");"full-stretched"===r.data("stretch-type")&&1===a.length&&a.css({"padding-left":0,"padding-right":0}),r.css({"border-left":0,"border-right":0})}),t(".siteorigin-panels-stretch.panel-row-style").length&&t(window).trigger("panelsStretchRows")};t(window).on("resize load",r),r(),t("body").removeClass("siteorigin-panels-before-js")});
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === Page Builder by SiteOrigin ===
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,6 +96,9 @@ We've tried to ensure that Page Builder is compatible with most plugin widgets.
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.
1
  === Page Builder by SiteOrigin ===
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
5
+ Stable tag: 2.6.4
6
+ Build time: 2018-04-04T19:32:31+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.4 - 4 April 2018 =
100
+ * Only call widget `enqueue_admin_scripts` function for WP core JS widgets.
101
+
102
  = 2.6.3 - 6 March 2018 =
103
  * Use `delete_post_meta_by_key` instead of direct DB query to clear old cache renders.
104
  * Removed special handling for retrieving data from TinyMCE editor fields. Just use the field value directly.
siteorigin-panels.php CHANGED
@@ -3,7 +3,7 @@
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
@@ -11,12 +11,12 @@ 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
 
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.4
7
  Author: SiteOrigin
8
  Author URI: https://siteorigin.com
9
  License: GPL3
11
  Donate link: http://siteorigin.com/page-builder/#donate
12
  */
13
 
14
+ define( 'SITEORIGIN_PANELS_VERSION', '2.6.4' );
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', '-264' );
20
 
21
  require_once plugin_dir_path( __FILE__ ) . 'inc/functions.php';
22