SiteOrigin Widgets Bundle - Version 1.16.1

Version Description

  • 20 April 2020 ==
  • Accordion: When hiding panels, only search the current accordion and not nested accordions.
  • Slider Widgets: Removed slide navigation numbers from excerpt output.
  • Added support for custom icon styles.
  • Tabs: Fixed top/bottom tab alignment when tab position is set to right/left.
  • Post Carousel: Prevent themes from adjusting the thumbnail top margin.
  • Improved the reliability of widget description translations. Updated various widget descriptions.
  • Editor: Resolved the notice appearing when post meta wasn't available.
  • Simple Masonry: Item labels - If the item title field isn't populated use the image title field.
  • Hero: Added a setting to vertically align the slide contents.
  • Updated jQuery TouchSwipe.
  • Sliders: Fixed pagination spacing when HTML optimization is in use.
  • Layout Slider: Set frame labels based on the content inserted.
  • Slider: Set frame labels based on the content inserted.
  • Contact Form: Added placeholder support to the dropdown select field. Used if the field label position is set to Inside.
  • Contact Form: Added Required support for the dropdown select field.
  • FontAwesome: Moved Brands to the last position in dropdown list.
  • Layout Slider: Added a setting to vertically align the slide contents.
Download this release

Release Info

Developer gpriday
Plugin Icon 128x128 SiteOrigin Widgets Bundle
Version 1.16.1
Comparing to
See all releases

Code changes from version 1.16.0 to 1.16.1

Files changed (44) hide show
  1. base/base.php +10 -5
  2. base/inc/attachments.php +5 -7
  3. base/inc/fields/icon.class.php +39 -8
  4. base/inc/fields/posts.class.php +1 -1
  5. base/inc/widgets/base-slider.class.php +1 -1
  6. base/js/admin.js +18 -3
  7. base/js/admin.min.js +1 -1
  8. css/slider/slider.css +1 -1
  9. icons/fontawesome/filter.php +1 -1
  10. icons/icons.php +1 -1
  11. js/jquery.touchSwipe.js +1737 -1682
  12. js/jquery.touchSwipe.min.js +14 -1
  13. lang/so-widgets-bundle.pot +106 -178
  14. readme.txt +944 -925
  15. so-widgets-bundle.php +2 -2
  16. widgets/accordion/accordion.php +1 -1
  17. widgets/accordion/js/accordion.js +1 -1
  18. widgets/accordion/js/accordion.min.js +1 -1
  19. widgets/button/button.php +1 -1
  20. widgets/contact/contact.php +4 -4
  21. widgets/contact/fields/select.class.php +14 -1
  22. widgets/cta/cta.php +1 -1
  23. widgets/editor/editor.php +4 -2
  24. widgets/features/features.php +1 -1
  25. widgets/google-map/google-map.php +1 -1
  26. widgets/headline/headline.php +1 -1
  27. widgets/hero/hero.php +8 -0
  28. widgets/hero/styles/default.less +7 -0
  29. widgets/icon/icon.php +1 -1
  30. widgets/image-grid/image-grid.php +1 -1
  31. widgets/image/image.php +1 -1
  32. widgets/layout-slider/layout-slider.php +18 -3
  33. widgets/layout-slider/styles/default.less +7 -0
  34. widgets/post-carousel/css/style.css +1 -1
  35. widgets/post-carousel/post-carousel.php +1 -1
  36. widgets/price-table/price-table.php +1 -1
  37. widgets/simple-masonry/simple-masonry.php +11 -2
  38. widgets/slider/slider.php +19 -6
  39. widgets/social-media-buttons/social-media-buttons.php +1 -1
  40. widgets/tabs/styles/default.less +11 -13
  41. widgets/tabs/tabs.php +1 -1
  42. widgets/taxonomy/taxonomy.php +1 -1
  43. widgets/testimonial/testimonial.php +2 -2
  44. widgets/video/video.php +1 -1
base/base.php CHANGED
@@ -69,11 +69,6 @@ add_action('wp_ajax_siteorigin_widgets_get_icons', 'siteorigin_widget_get_icon_l
69
  */
70
  function siteorigin_widget_get_icon($icon_value, $icon_styles = false) {
71
  if( empty( $icon_value ) ) return false;
72
- $value_parts = SiteOrigin_Widget_Field_Icon::get_value_parts( $icon_value );
73
- $family = $value_parts['family'];
74
- $style = empty( $value_parts['style'] ) ? null : $value_parts['style'];
75
- $icon = $value_parts['icon'];
76
- if( empty( $family ) || empty( $icon ) ) return false;
77
 
78
  static $widget_icon_families;
79
  static $widget_icons_enqueued = array();
@@ -81,6 +76,16 @@ function siteorigin_widget_get_icon($icon_value, $icon_styles = false) {
81
  if ( empty( $widget_icon_families ) ) {
82
  $widget_icon_families = apply_filters('siteorigin_widgets_icon_families', array() );
83
  }
 
 
 
 
 
 
 
 
 
 
84
  if ( empty( $widget_icon_families[ $family ] ) ||
85
  empty( $widget_icon_families[ $family ]['icons'][ $icon ] ) ) {
86
  return false;
69
  */
70
  function siteorigin_widget_get_icon($icon_value, $icon_styles = false) {
71
  if( empty( $icon_value ) ) return false;
 
 
 
 
 
72
 
73
  static $widget_icon_families;
74
  static $widget_icons_enqueued = array();
76
  if ( empty( $widget_icon_families ) ) {
77
  $widget_icon_families = apply_filters('siteorigin_widgets_icon_families', array() );
78
  }
79
+
80
+ // Get an array of available icon families styles to pass to SiteOrigin_Widget_Field_Icon::get_value_parts()
81
+ $icon_families_styles = SiteOrigin_Widget_Field_Icon::get_icon_families_styles( $widget_icon_families );
82
+
83
+ $value_parts = SiteOrigin_Widget_Field_Icon::get_value_parts( $icon_value, $icon_families_styles );
84
+ $family = $value_parts['family'];
85
+ $style = empty( $value_parts['style'] ) ? null : $value_parts['style'];
86
+ $icon = $value_parts['icon'];
87
+ if( empty( $family ) || empty( $icon ) ) return false;
88
+
89
  if ( empty( $widget_icon_families[ $family ] ) ||
90
  empty( $widget_icon_families[ $family ]['icons'][ $icon ] ) ) {
91
  return false;
base/inc/attachments.php CHANGED
@@ -32,18 +32,14 @@ function siteorigin_widgets_get_attachment_image_src( $attachment, $size, $fallb
32
  return false;
33
  }
34
 
35
- function siteorigin_widgets_get_attachment_image( $attachment, $size, $fallback ){
36
  if( !empty( $attachment ) ) {
37
- return wp_get_attachment_image( $attachment, $size );
38
  }
39
  else {
40
  $src = siteorigin_widgets_get_attachment_image_src( $attachment, $size, $fallback );
41
  if( empty($src[0]) ) return '';
42
 
43
- $atts = array(
44
- 'src' => $src[0],
45
- );
46
-
47
  if ( function_exists( 'wp_get_attachment_image_srcset' ) ) {
48
  $atts['srcset'] = wp_get_attachment_image_srcset( $attachment, $size );
49
  }
@@ -51,6 +47,8 @@ function siteorigin_widgets_get_attachment_image( $attachment, $size, $fallback
51
  $atts['sizes'] = wp_get_attachment_image_sizes( $attachment, $size );
52
  }
53
 
 
 
54
  if( !empty($src[1]) ) $atts['width'] = $src[1];
55
  if( !empty($src[2]) ) $atts['height'] = $src[2];
56
 
@@ -106,4 +104,4 @@ function siteorigin_widgets_get_image_size( $size ) {
106
  }
107
 
108
  return null;
109
- }
32
  return false;
33
  }
34
 
35
+ function siteorigin_widgets_get_attachment_image( $attachment, $size, $fallback, $atts = array() ){
36
  if( !empty( $attachment ) ) {
37
+ return wp_get_attachment_image( $attachment, $size, false, $atts );
38
  }
39
  else {
40
  $src = siteorigin_widgets_get_attachment_image_src( $attachment, $size, $fallback );
41
  if( empty($src[0]) ) return '';
42
 
 
 
 
 
43
  if ( function_exists( 'wp_get_attachment_image_srcset' ) ) {
44
  $atts['srcset'] = wp_get_attachment_image_srcset( $attachment, $size );
45
  }
47
  $atts['sizes'] = wp_get_attachment_image_sizes( $attachment, $size );
48
  }
49
 
50
+ $atts['src'] = $src[0];
51
+
52
  if( !empty($src[1]) ) $atts['width'] = $src[1];
53
  if( !empty($src[2]) ) $atts['height'] = $src[2];
54
 
104
  }
105
 
106
  return null;
107
+ }
base/inc/fields/icon.class.php CHANGED
@@ -17,14 +17,19 @@ class SiteOrigin_Widget_Field_Icon extends SiteOrigin_Widget_Field_Base {
17
 
18
  protected function render_field( $value, $instance ) {
19
  $widget_icon_families = $this->get_widget_icon_families();
20
- $value_parts = self::get_value_parts( $value );
 
 
 
 
 
21
  if ( ! empty( $value ) ) {
22
  $value_family = $value_parts['family'];
23
  $value_style = empty( $value_parts['style'] ) ? '' : ( '-' . $value_parts['style'] );
24
  $value = $value_parts['family'] . $value_style . '-' . $value_parts['icon'];
25
 
26
  } else {
27
- $value_family = 'fontawesome';
28
  }
29
  ?>
30
 
@@ -82,8 +87,12 @@ class SiteOrigin_Widget_Field_Icon extends SiteOrigin_Widget_Field_Base {
82
  $sanitized_value = '';
83
  }
84
 
85
- $value_parts = self::get_value_parts( $sanitized_value );
86
  $widget_icon_families = $this->get_widget_icon_families();
 
 
 
 
 
87
  if( ! ( isset( $widget_icon_families[$value_parts['family']] ) && isset( $widget_icon_families[$value_parts['family']]['icons'][$value_parts['icon']] ) ) ) {
88
  $sanitized_value = isset( $this->default ) ? $this->default : '';
89
  }
@@ -113,14 +122,23 @@ class SiteOrigin_Widget_Field_Icon extends SiteOrigin_Widget_Field_Base {
113
  return $widget_icon_families;
114
  }
115
 
116
- static function get_value_parts( $value ) {
117
 
118
  list( $value_family, $value_icon ) = ( ! empty( $value ) && strpos( $value, '-' ) !== false ) ? explode( '-', $value, 2 ) : array('', '');
119
 
120
- $matched = preg_match( '/(sow\-fa\w?)\-/', $value_icon, $style_matches );
121
- if ( ! empty( $matched ) ) {
122
- $value_icon = str_replace( $style_matches[0], '', $value_icon );
123
- $value_style = $style_matches[1];
 
 
 
 
 
 
 
 
 
124
  }
125
 
126
  // Trigger loading of the icon families and their filters. This isn't ideal, but necessary to ensure possible
@@ -134,6 +152,19 @@ class SiteOrigin_Widget_Field_Icon extends SiteOrigin_Widget_Field_Base {
134
  ) );
135
  }
136
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  public function enqueue_scripts(){
138
  wp_enqueue_script( 'so-icon-field', plugin_dir_url( __FILE__ ) . 'js/icon-field' . SOW_BUNDLE_JS_SUFFIX . '.js', array( 'jquery' ), SOW_BUNDLE_VERSION );
139
  wp_enqueue_style( 'so-icon-field', plugin_dir_url( __FILE__ ) . 'css/icon-field.css', array( ), SOW_BUNDLE_VERSION );
17
 
18
  protected function render_field( $value, $instance ) {
19
  $widget_icon_families = $this->get_widget_icon_families();
20
+
21
+ // Get an array of available icon families styles to pass to self::get_value_parts()
22
+ $icon_families_styles = self::get_icon_families_styles( $widget_icon_families );
23
+
24
+ $value_parts = self::get_value_parts( $value, $icon_families_styles );
25
+
26
  if ( ! empty( $value ) ) {
27
  $value_family = $value_parts['family'];
28
  $value_style = empty( $value_parts['style'] ) ? '' : ( '-' . $value_parts['style'] );
29
  $value = $value_parts['family'] . $value_style . '-' . $value_parts['icon'];
30
 
31
  } else {
32
+ $value_family = key($widget_icon_families);
33
  }
34
  ?>
35
 
87
  $sanitized_value = '';
88
  }
89
 
 
90
  $widget_icon_families = $this->get_widget_icon_families();
91
+
92
+ $icon_families_styles = self::get_icon_families_styles( $widget_icon_families );
93
+
94
+ $value_parts = self::get_value_parts( $sanitized_value, $icon_families_styles );
95
+
96
  if( ! ( isset( $widget_icon_families[$value_parts['family']] ) && isset( $widget_icon_families[$value_parts['family']]['icons'][$value_parts['icon']] ) ) ) {
97
  $sanitized_value = isset( $this->default ) ? $this->default : '';
98
  }
122
  return $widget_icon_families;
123
  }
124
 
125
+ static function get_value_parts( $value, $icon_families_styles = null ) {
126
 
127
  list( $value_family, $value_icon ) = ( ! empty( $value ) && strpos( $value, '-' ) !== false ) ? explode( '-', $value, 2 ) : array('', '');
128
 
129
+ // Check if icon families have styles. See $this->sanitize_field_input()
130
+ if ( $icon_families_styles !== null ) {
131
+ foreach ( $icon_families_styles as $icon_family => $icon_family_styles ) {
132
+ foreach ( $icon_family_styles as $icon_family_style => $icon_family_style_name ) {
133
+ // Check the icon value for matching styles
134
+ if ( substr( $value_icon, 0, strlen( $icon_family_style ) ) === $icon_family_style ) {
135
+ $value_icon = substr( $value_icon, strlen( $icon_family_style . '-' ) );
136
+ $value_style = $icon_family_style;
137
+
138
+ break 2;
139
+ }
140
+ }
141
+ }
142
  }
143
 
144
  // Trigger loading of the icon families and their filters. This isn't ideal, but necessary to ensure possible
152
  ) );
153
  }
154
 
155
+ public static function get_icon_families_styles( $widget_icon_families ) {
156
+ // Store an array of icon family styles to pass to self::get_value_parts()
157
+ $icon_families_styles = [];
158
+
159
+ foreach ( $widget_icon_families as $key => $val ) {
160
+ if ( array_key_exists( 'styles', $val ) ) {
161
+ $icon_families_styles[ $key ] = $val[ 'styles' ];
162
+ }
163
+ }
164
+
165
+ return $icon_families_styles;
166
+ }
167
+
168
  public function enqueue_scripts(){
169
  wp_enqueue_script( 'so-icon-field', plugin_dir_url( __FILE__ ) . 'js/icon-field' . SOW_BUNDLE_JS_SUFFIX . '.js', array( 'jquery' ), SOW_BUNDLE_VERSION );
170
  wp_enqueue_style( 'so-icon-field', plugin_dir_url( __FILE__ ) . 'css/icon-field.css', array( ), SOW_BUNDLE_VERSION );
base/inc/fields/posts.class.php CHANGED
@@ -137,7 +137,7 @@ class SiteOrigin_Widget_Field_Posts extends SiteOrigin_Widget_Field_Container_Ba
137
  'additional' => array(
138
  'type' => 'text',
139
  'label' => __( 'Additional', 'so-widgets-bundle' ),
140
- 'description' => __( 'Additional query arguments. See <a href="http://codex.wordpress.org/Function_Reference/query_posts" target="_blank" rel="noopener noreferrer">query_posts</a>.', 'so-widgets-bundle' ),
141
  ),
142
  );
143
  }
137
  'additional' => array(
138
  'type' => 'text',
139
  'label' => __( 'Additional', 'so-widgets-bundle' ),
140
+ 'description' => __( 'Additional query arguments. See <a href="https://developer.wordpress.org/reference/functions/query_posts/" target="_blank" rel="noopener noreferrer">query_posts</a>.', 'so-widgets-bundle' ),
141
  ),
142
  );
143
  }
base/inc/widgets/base-slider.class.php CHANGED
@@ -197,7 +197,7 @@ abstract class SiteOrigin_Widget_Base_Slider extends SiteOrigin_Widget {
197
  ?>
198
  <ol class="sow-slider-pagination">
199
  <?php foreach($frames as $i => $frame) : ?>
200
- <li><a href="#" data-goto="<?php echo $i ?>" aria-label="<?php printf( __( 'display slide %s', 'so-widgets-bundle' ), $i+1 ) ?>"><?php echo $i+1 ?></a></li>
201
  <?php endforeach; ?>
202
  </ol>
203
 
197
  ?>
198
  <ol class="sow-slider-pagination">
199
  <?php foreach($frames as $i => $frame) : ?>
200
+ <li><a href="#" data-goto="<?php echo $i ?>" aria-label="<?php printf( __( 'display slide %s', 'so-widgets-bundle' ), $i+1 ) ?>"></a></li>
201
  <?php endforeach; ?>
202
  </ol>
203
 
base/js/admin.js CHANGED
@@ -733,15 +733,30 @@ var sowbForms = window.sowbForms || {};
733
  var $parentRepeater = $el.closest('.siteorigin-widget-field-repeater');
734
  var itemTop = $el.find('> .siteorigin-widget-field-repeater-item-top');
735
  var itemLabel = $parentRepeater.data('item-label');
736
- if (itemLabel && itemLabel.selector) {
 
737
  var updateLabel = function () {
738
- var functionName = ( itemLabel.hasOwnProperty('valueMethod') && itemLabel.valueMethod ) ? itemLabel.valueMethod : 'val';
739
- var txt = $el.find(itemLabel.selector)[functionName]();
 
 
 
 
 
 
 
 
 
 
 
 
740
  if (txt) {
741
  if (txt.length > 80) {
742
  txt = txt.substr(0, 79) + '...';
743
  }
744
  itemTop.find('h4').text(txt);
 
 
745
  }
746
  };
747
  updateLabel();
733
  var $parentRepeater = $el.closest('.siteorigin-widget-field-repeater');
734
  var itemTop = $el.find('> .siteorigin-widget-field-repeater-item-top');
735
  var itemLabel = $parentRepeater.data('item-label');
736
+ var defaultLabel = $el.parents('.siteorigin-widget-field-repeater').data('item-name');
737
+ if ( itemLabel && ( itemLabel.hasOwnProperty( 'selector' ) || itemLabel.hasOwnProperty( 'selectorArray' ) ) ) {
738
  var updateLabel = function () {
739
+ var functionName, txt, selectorRow;
740
+ if ( itemLabel.hasOwnProperty( 'selectorArray' ) ) {
741
+ for ( var i = 0 ; i < itemLabel.selectorArray.length ; i++ ) {
742
+ selectorRow = itemLabel.selectorArray[ i ];
743
+ functionName = ( selectorRow.hasOwnProperty( 'valueMethod' ) && selectorRow.valueMethod ) ? selectorRow.valueMethod : 'val';
744
+ txt = $el.find( selectorRow.selector )[ functionName ]();
745
+ if ( txt ) {
746
+ break;
747
+ }
748
+ }
749
+ } else {
750
+ functionName = ( itemLabel.hasOwnProperty( 'valueMethod' ) && itemLabel.valueMethod ) ? itemLabel.valueMethod : 'val';
751
+ txt = $el.find( itemLabel.selector )[ functionName ]();
752
+ }
753
  if (txt) {
754
  if (txt.length > 80) {
755
  txt = txt.substr(0, 79) + '...';
756
  }
757
  itemTop.find('h4').text(txt);
758
+ } else {
759
+ itemTop.find('h4').text(defaultLabel);
760
  }
761
  };
762
  updateLabel();
base/js/admin.min.js CHANGED
@@ -1 +1 @@
1
- var sowbForms=window.sowbForms||{};!function(e){e.fn.sowSetupForm=function(){return e(this).each((function(i,t){var r,n=e(t),a=!0,s=e("body"),o=n.find("input[name]");if(o.length&&-1!==o.attr("name").indexOf("__i__"))return this;if(n.is(".siteorigin-widget-form-main")){if(!0===n.data("sow-form-setup"))return!0;if(s.hasClass("widgets-php")&&!n.is(":visible")&&0===n.closest(".panel-dialog").length)return!0;n.on("sowstatechange",(function(i,t,r){n.find("[data-state-handler]").each((function(){var i,n,s,o,d,l,g=e(this),f=e.extend({},g.data("state-handler"),a?g.data("state-handler-initial"):{});if(0===Object.keys(f).length)return!0;var c={},p=sowbForms.getContainerFieldId(g,"repeater",".siteorigin-widget-field-repeater-item");if(!1!==p){var u={};for(var w in f)u[w.replace("{$repeater}",p)]=f[w];f=u}var m=sowbForms.getContainerFieldId(g,"widget",".siteorigin-widget-widget");if(!1!==m){var v={};for(var h in f){var b=h.match(/_else\[(.*)\]|(.*)\[(.*)\]/);v[b&&b.length&&void 0===b[1]?b[2]+"_"+m+"["+b[3]+"]":"_else["+b[1]+"_"+m+"]"]=f[h]}f=v}for(var y in f)if(d=!1,null!==(i=y.match(/^([a-zA-Z0-9_-]+)(\[([a-zA-Z0-9_\-,]+)\])?(\[\])?$/))){if(n={group:"default",name:"",multi:!1},void 0!==i[2]?(n.group=i[1],n.name=i[3]):n.name=i[0],n.multi=void 0!==i[4],"_else"===n.group)n.group=n.name,n.name="",d=n.group===t&&void 0===c[n.group];else{l=n.name.split(",").map((function(e){return e.trim()}));for(var F=0;F<l.length&&!(d=n.group===t&&l[F]===r);F++);}if(d){s=f[y],n.multi||(s=[s]);for(F=0;F<s.length;F++){if((o=void 0!==s[F][1]&&Boolean(s[F][1])?g.find(s[F][1]):g)[s[F][0]].apply(o,void 0!==s[F][2]?s[F][2]:[]),o.is(".siteorigin-widget-field:visible"))if(o.is(".siteorigin-widget-field-type-section"))o.find("> .siteorigin-widget-section > .siteorigin-widget-field").trigger("sowsetupformfield");else o.trigger("sowsetupformfield")}c[n.group]=!0}}}))})),n.sowSetupPreview(),r=n;var d=n.find(".siteorigin-widget-teaser");if(d.find(".dashicons-dismiss").click((function(){var i=e(this);e.get(i.data("dismiss-url")),d.slideUp("normal",(function(){d.remove()}))})),!n.data("backupDisabled")){var l=n.find("> .siteorigin-widgets-form-id").val(),g=n.find("> .siteorigin-widgets-form-timestamp"),f=parseInt(g.val()||0),c=JSON.parse(sessionStorage.getItem(l));c&&(c._sow_form_timestamp>f?sowbForms.displayNotice(n,soWidgets.backup.newerVersion,soWidgets.backup.replaceWarning,[{label:soWidgets.backup.restore,callback:function(e){sowbForms.setWidgetFormValues(r,c),e.slideUp("fast",(function(){e.remove()}))}},{label:soWidgets.backup.dismiss,callback:function(e){e.slideUp("fast",(function(){sessionStorage.removeItem(l),e.remove()}))}}]):sessionStorage.removeItem(l)),n.change((function(){g.val((new Date).getTime());var e=sowbForms.getWidgetFormValues(n);sessionStorage.setItem(l,JSON.stringify(e))}))}}else r=n.closest(".siteorigin-widget-form-main");r.find("> .siteorigin-widgets-form-id").val();var p=n.find("> .siteorigin-widget-field");p.find("> .siteorigin-widget-section").sowSetupForm();var u=p.find("> .siteorigin-widget-widget");u.find("> .siteorigin-widget-section").sowSetupForm(),u.filter(":not(:has(> .siteorigin-widget-section))").sowSetupForm(),p.find(".siteorigin-widget-input").each((function(i,t){null===e(t).data("original-name")&&e(t).data("original-name",e(t).attr("name"))})),p.find("> .siteorigin-widget-field-repeater").sowSetupRepeater(),n.find(".siteorigin-widget-field-repeater-item").sowSetupRepeaterItems(),p.find("> .siteorigin-widget-input-color").each((function(){var i=e(this),t={change:function(i,t){setTimeout((function(){e(i.target).trigger("change")}),100)}};i.data("defaultColor")&&(t.defaultColor=i.data("defaultColor")),i.wpColorPicker(t)}));var w=function(){e(this).toggleClass("siteorigin-widget-section-visible"),e(this).parent().find("> .siteorigin-widget-section, > .siteorigin-widget-widget > .siteorigin-widget-section").slideToggle("fast",(function(){(e(window).resize(),e(this).find("> .siteorigin-widget-field-container-state").val(e(this).is(":visible")?"open":"closed"),e(this).is(":visible"))&&e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")}))};p.filter(".siteorigin-widget-field-type-widget, .siteorigin-widget-field-type-section").find("> label").click(w),p.filter(".siteorigin-widget-field-type-posts").find(".posts-container-label-wrapper").click(w),p.filter(".siteorigin-widget-field-type-slider").each((function(){var i=e(this),t=i.find('input[type="number"]'),r=i.find(".siteorigin-widget-value-slider");r.slider({max:parseFloat(t.attr("max")),min:parseFloat(t.attr("min")),step:parseFloat(t.attr("step")),value:parseFloat(t.val()),slide:function(e,r){t.val(parseFloat(r.value)),t.trigger("change"),i.find(".siteorigin-widget-slider-value").html(r.value)}}),t.change((function(e,i){i&&i.silent||r.slider("value",parseFloat(t.val()))}))})),p.filter(".siteorigin-widget-field-type-link").each((function(){var i=e(this),t=function(){var t=i.find(".content-text-search"),r=t.val(),n=t.data("postTypes"),a=i.find("ul.posts").empty().addClass("loading");e.get(soWidgets.ajaxurl,{action:"so_widgets_search_posts",query:r,postTypes:n},(function(i){for(var t=0;t<i.length;t++)""===i[t].label&&(i[t].label="&nbsp;"),a.append(e("<li>").addClass("post").html(i[t].label+"<span>("+i[t].type+")</span>").data(i[t]));a.removeClass("loading")}))};i.find(".select-content-button, .button-close").click((function(r){r.preventDefault(),e(this).blur();var n=i.find(".existing-content-selector");n.toggle(),n.is(":visible")&&0===n.find("ul.posts li").length&&t()})),i.on("click",".posts li",(function(t){t.preventDefault();var r=e(this);i.find("input.siteorigin-widget-input").val("post: "+r.data("value")),i.change(),i.find(".existing-content-selector").toggle()}));var r=null;i.find(".content-text-search").keyup((function(){null!==r&&clearTimeout(r),r=setTimeout((function(){t()}),500)}))})),void 0!==jQuery.fn.soPanelsSetupBuilderWidget&&p.filter(".siteorigin-widget-field-type-builder").each((function(){e(this).find("> .siteorigin-page-builder-field").each((function(){var i=e(this);i.soPanelsSetupBuilderWidget({builderType:i.data("type")})}))}));var m=function(){var i=e(this),t=i.closest("[data-state-emitter]").data("state-emitter");if(void 0!==t){var n=function(t,r){if(void 0===sowEmitters[t.callback]||"_"===t.callback.substr(0,1))return r;if(i.is('[type="radio"]')&&!i.is(":checked"))return r;var n=sowbForms.getContainerFieldId(i,"repeater",".siteorigin-widget-field-repeater-item");!1!==n&&(t.args=t.args.map((function(e){return e.replace("{$repeater}",n)})));var a=sowbForms.getContainerFieldId(i,"widget",".siteorigin-widget-widget");!1===a||t.hasOwnProperty("widgetFieldId")||(t.widgetFieldId=a,t.args=t.args.map((function(e){return e="conditional"===t.callback?e.replace(/(.*)(\[.*)/,"$1_"+a+"$2"):e+"_"+a})));var s=i.is('[type="checkbox"]')?i.is(":checked"):i.val();return e.extend(r,sowEmitters[t.callback](s,t.args))},a={default:""};void 0===t.length&&(t=[t]);for(var s=0;s<t.length;s++)a=n(t[s],a);var o=r.data("states");for(var d in void 0===o&&(o={default:""}),a)void 0!==o[d]&&a[d]===o[d]||(o[d]=a[d],r.trigger("sowstatechange",[d,a[d]]));r.data("states",o)}};p.filter("[data-state-emitter]").each((function(){var i=e(this).find(".siteorigin-widget-input");i.on("keyup change",m),i.each((function(){var i=e(this);i.is(":radio")?i.is(":checked")&&m.call(i[0]):m.call(i[0])}))})),n.trigger("sowsetupform",p).data("sow-form-setup",!0),p.trigger("sowsetupformfield"),n.find(".siteorigin-widget-field-repeater-item").trigger("updateFieldPositions"),(s.hasClass("wp-customizer")||s.hasClass("widgets-php"))&&n.closest(".ui-sortable").on("sortstop",(function(e,i){i.item.find(".siteorigin-widget-form").find("> .siteorigin-widget-field").trigger("sowsetupformfield")})),a=!1}))},e.fn.sowSetupPreview=function(){var i=e(this);i.siblings(".siteorigin-widget-preview").find("> a").click((function(t){t.preventDefault();var r=sowbForms.getWidgetFormValues(i),n=e(e("#so-widgets-bundle-tpl-preview-dialog").html().trim()).appendTo("body");n.find('input[name="data"]').val(JSON.stringify(r)),n.find('input[name="class"]').val(i.data("class")),n.find("iframe").on("load",(function(){e(this).css("visibility","visible")})),n.find("form").submit(),n.find(".close").click((function(){n.remove()}))}))},e.fn.sowSetupRepeater=function(){return e(this).each((function(i,t){var r=e(t),n=r.find(".siteorigin-widget-field-repeater-items"),a=r.data("repeater-name");n.bind("updateFieldPositions",(function(){var i=e(this),t=i.find("> .siteorigin-widget-field-repeater-item");t.each((function(i,t){e(t).find(".siteorigin-widget-input").each((function(t,r){var n=e(r).data("repeater-positions");void 0===n&&(n={}),n[a]=i,e(r).data("repeater-positions",n)}))})),i.find(".siteorigin-widget-input").each((function(i,t){var r=e(t),n=r.data("repeater-positions");if(void 0!==n){var a=r.attr("data-original-name");if(a||(r.attr("data-original-name",r.attr("name")),a=r.attr("name")),!a)return;if(n)for(var s in n)a=a.replace("#"+s+"#",n[s]);r.attr("name",a)}})),i.data("initialSetup")||(i.find(".siteorigin-widget-input").each((function(i,t){var r=e(t);r.prop("checked",r.prop("defaultChecked"))})),i.data("initialSetup",!0));var n=r.data("scroll-count")?parseInt(r.data("scroll-count")):0;if(n>0&&t.length>n){var s=t.first().outerHeight();i.css("max-height",s*n).css("overflow","auto")}else i.css("max-height","").css("overflow","")})),n.sortable({handle:".siteorigin-widget-field-repeater-item-top",items:"> .siteorigin-widget-field-repeater-item",update:function(){n.find('input[type="radio"].siteorigin-widget-input').attr("name",""),n.trigger("updateFieldPositions"),r.trigger("change")},sortstop:function(i,t){t.item.is(".siteorigin-widget-field-repeater-item")?t.item.find("> .siteorigin-widget-field-repeater-item-form").each((function(){e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")})):t.item.find(".siteorigin-widget-form").find("> .siteorigin-widget-field").trigger("sowsetupformfield");r.trigger("change")}}),n.trigger("updateFieldPositions"),r.find("> .siteorigin-widget-field-repeater-add").disableSelection().click((function(i){i.preventDefault(),r.closest(".siteorigin-widget-field-repeater").sowAddRepeaterItem().find("> .siteorigin-widget-field-repeater-items").slideDown("fast",(function(){e(window).resize()}))})),r.find("> .siteorigin-widget-field-repeater-top > .siteorigin-widget-field-repeater-expand").click((function(i){i.preventDefault(),r.closest(".siteorigin-widget-field-repeater").find("> .siteorigin-widget-field-repeateritems-").slideToggle("fast",(function(){e(window).resize()}))}))}))},e.fn.sowAddRepeaterItem=function(){return e(this).each((function(i,t){var r=e(t),n=r.find("> .siteorigin-widget-field-repeater-items").children().length+1,a=e("<div>"+r.find("> .siteorigin-widget-field-repeater-item-html").html()+"</div>");a.find(".siteorigin-widget-input[data-name]").each((function(){var i=e(this);0===i.closest(".siteorigin-widget-field-repeater-item-html").length&&i.attr("name",e(this).data("name"))}));var s="";a.find("> .siteorigin-widget-field").each((function(i,t){var r=t.outerHTML;e(t).is(".siteorigin-widget-field-type-repeater")||(r=r.replace(/_id_/g,n)),s+=r}));var o=void 0!==r.attr("readonly"),d=e('<div class="siteorigin-widget-field-repeater-item ui-draggable" />').append(e('<div class="siteorigin-widget-field-repeater-item-top" />').append(e('<div class="siteorigin-widget-field-expand" />')).append(o?"":e('<div class="siteorigin-widget-field-copy" />')).append(o?"":e('<div class="siteorigin-widget-field-remove" />')).append(e("<h4 />").html(r.data("item-name")))).append(e('<div class="siteorigin-widget-field-repeater-item-form" />').html(s));r.find("> .siteorigin-widget-field-repeater-items").append(d).sortable("refresh").trigger("updateFieldPositions"),d.sowSetupRepeaterItems(),d.hide().slideDown("fast",(function(){e(window).resize()})),r.trigger("change")}))},e.fn.sowRemoveRepeaterItem=function(){return e(this).each((function(i,t){var r=e(this).closest(".siteorigin-widget-field-repeater-items");e(this).remove(),r.sortable("refresh").trigger("updateFieldPositions"),e(t).trigger("change")}))},e.fn.sowSetupRepeaterItems=function(){return e(this).each((function(i,t){var r=e(t);if(void 0===r.data("sowrepeater-actions-setup")){var n=r.closest(".siteorigin-widget-field-repeater"),a=r.find("> .siteorigin-widget-field-repeater-item-top"),s=n.data("item-label");if(s&&s.selector){var o=function(){var e=s.hasOwnProperty("valueMethod")&&s.valueMethod?s.valueMethod:"val",i=r.find(s.selector)[e]();i&&(i.length>80&&(i=i.substr(0,79)+"..."),a.find("h4").text(i))};o();var d=s.hasOwnProperty("updateEvent")&&s.updateEvent?s.updateEvent:"change";r.bind(d,o)}a.click((function(i){"siteorigin-widget-field-remove"!==i.target.className&&"siteorigin-widget-field-copy"!==i.target.className&&(i.preventDefault(),e(this).closest(".siteorigin-widget-field-repeater-item").find(".siteorigin-widget-field-repeater-item-form").eq(0).slideToggle("fast",(function(){e(window).resize(),e(this).is(":visible")?(e(this).trigger("slideToggleOpenComplete"),e(this).find(".siteorigin-widget-field-type-section > .siteorigin-widget-section > .siteorigin-widget-field,> .siteorigin-widget-field").each((function(i,t){var r=e(t);r.is(":visible")&&r.trigger("sowsetupformfield")}))):e(this).trigger("slideToggleCloseComplete")})))})),a.find(".siteorigin-widget-field-remove").click((function(i,t){i.preventDefault();var r=e(this).closest(".siteorigin-widget-field-repeater-items"),a=e(this).closest(".siteorigin-widget-field-repeater-item"),s=function(){a.remove(),r.sortable("refresh").trigger("updateFieldPositions"),e(window).resize(),n.trigger("change")};t&&t.silent?s():confirm(soWidgets.sure)&&a.slideUp("fast",s)})),a.find(".siteorigin-widget-field-copy").click((function(i){i.preventDefault();var t=e(this).closest(".siteorigin-widget-form-main"),n=e(this).closest(".siteorigin-widget-field-repeater-item"),a=n.clone(),s=n.closest(".siteorigin-widget-field-repeater-items"),o=s.children().length,d={};a.find("*[name]").each((function(){var i=e(this),s=i.attr("id"),l=i.attr("name");if(i.is("textarea")&&i.parent().is(".wp-editor-container")&&"undefined"!=typeof tinymce){i.parent().empty().append(i),i.css("display","");var g=tinymce.get(s);g&&i.val(g.getContent())}else if(i.is(".wp-color-picker")){var f=i.closest(".wp-picker-container"),c=i.closest(".siteorigin-widget-field");f.remove(),c.append(i.remove())}else{var p=s?n.find("#"+s):n.find('[name="'+l+'"]');p.length&&null!=p.val()&&i.val(p.val())}if(s){var u,w;if(i.is('[type="radio"]')){u=s.replace(/-\d+-\d+$/,"");var m=s.replace(/-\d+$/,"");if(!d[u]){var v={};d[u]=t.find(".siteorigin-widget-input[id^="+u+"]").not("[id*=_id_]").filter((function(i,t){var r=e(t).attr("name");return!v[r]&&(v[r]=!0,!0)})).length+1}var h=u+"-"+d[u];w=h+s.match(/-\d+$/)[0],a.find("label[for="+m+"]").attr("for",h)}else F=new RegExp("-\\d+$"),u=s.replace(F,""),d[u]||(d[u]=t.find(".siteorigin-widget-input[id^="+u+"]").not("[id*=_id_]").length+1),w=u+"-"+d[u]++;if(i.attr("id",w),i.is(".wp-editor-area")){var b=i.closest(".siteorigin-widget-tinymce-container"),y=b.data("media-buttons");if(y&&y.html){var F=new RegExp(s,"g");y.html=y.html.replace(F,w),b.data("media-buttons",y)}}a.find("label[for="+s+"]").attr("for",w),a.find("[id*="+s+"]").each((function(){var i=e(this).attr("id").replace(s,w);e(this).attr("id",i)})),"undefined"!=typeof tinymce&&tinymce.get(w)&&tinymce.get(w).remove()}var k=n.parents(".siteorigin-widget-field-repeater").length,_=e("body");(_.hasClass("wp-customizer")||_.hasClass("widgets-php"))&&0===r.closest(".panel-dialog").length&&(k+=1);var C=l.replace(new RegExp("((?:.*?\\[\\d+\\]){"+(k-1).toString()+"})?(.*?\\[)\\d+(\\])"),"$1$2"+o.toString()+"$3");i.attr("name",C),i.data("original-name",C)})),s.append(a).sortable("refresh").trigger("updateFieldPositions"),a.sowSetupRepeaterItems(),a.hide().slideDown("fast",(function(){e(window).resize()})),r.trigger("change")})),r.find("> .siteorigin-widget-field-repeater-item-form").sowSetupForm(),r.data("sowrepeater-actions-setup",!0)}}))},sowbForms.getContainerFieldId=function(e,i,t){var r=i+"FieldId";this.hasOwnProperty(r)||(this[r]=1);var n=e.closest(t);if(n.length){var a=n.data("field-id");return void 0===a&&(a=this[r]++),n.data("field-id",a),a}return!1},sowbForms.getWidgetFieldVariable=function(e,i,t){var r=window.sow_field_javascript_variables[e];i=i.replace(/\[#.*?#\]/g,"");for(var n=/[a-zA-Z0-9\-]+(?:\[c?[0-9]+\])?\[(.*)\]/.exec(i)[1].split("]["),a=n.length?r:null;n.length;)a=a[n.shift()];return a[t]},sowbForms.fetchWidgetVariable=function(i,t,r){window.sowVars=window.sowVars||{},void 0===window.sowVars[t]?e.post(soWidgets.ajaxurl,{action:"sow_get_javascript_variables",widget:t,key:i},(function(e){window.sowVars[t]=e,r(window.sowVars[t][i])})):r(window.sowVars[t][i])},sowbForms.getWidgetIdBase=function(e){return e.data("id-base")},sowbForms.getWidgetFormValues=function(i){if(_.isUndefined(i))return null;var t={};return i.find("*[name]").each((function(){var i=e(this);try{var r=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(_.isEmpty(r))return!0;var n=(r=r[1]).split("][");n=n.map((function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e}));var a=t,s=null,o=_.isString(i.attr("type"))?i.attr("type").toLowerCase():null;if("checkbox"===o)s=!!i.is(":checked")&&(""===i.val()||i.val());else if("radio"===o){if(!i.is(":checked"))return;s=i.val()}else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var d=null;"undefined"!=typeof tinyMCE&&(d=tinyMCE.get(i.attr("id"))),s=null===d||"function"!=typeof d.getContent||d.isHidden()?i.val():d.getContent()}else if("SELECT"===i.prop("tagName")){var l=i.find("option:selected");1===l.length?s=i.find("option:selected").val():l.length>1&&(s=_.map(i.find("option:selected"),(function(i,t){return e(i).val()})))}else s=i.val();for(var g=0;g<n.length;g++)g===n.length-1?""===n[g]?a.push(s):a[n[g]]=s:(_.isUndefined(a[n[g]])&&(_.isNumber(n[g+1])||""===n[g+1]?a[n[g]]=[]:a[n[g]]={}),a=a[n[g]])}catch(e){console.error("Field ["+i.attr("name")+"] could not be processed and was skipped - "+e.message)}})),t},sowbForms.setWidgetFormValues=function(i,t,r,n){r=r||!1,n=void 0!==n&&n||void 0===n;var a=0,s=function(i,t){10!=++a?(i.find("> .siteorigin-widget-field-type-repeater,> .siteorigin-widget-field-type-section > .siteorigin-widget-section > .siteorigin-widget-field-type-repeater").each((function(i,n){var a=e(this),o=a.find("> .siteorigin-widget-field-repeater"),d=o.data("repeaterName"),l=t.hasOwnProperty(d)?t[d]:null;if(a.parent().is(".siteorigin-widget-section")){var g=o.data("element-name");g=g.replace(/\[#.*?#\]/g,"");for(var f=/[a-zA-Z0-9\-]+(?:\[c?[0-9]+\])?\[(.*)\]/.exec(g)[1].split("]["),c=f.length?t:null;f.length;){var p=f.shift();c=c.hasOwnProperty(p)?c[p]:c}l=c}if(l&&Array.isArray(l)){var u=o.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item"),w=l.length,m=u.length;if(w>m)for(var v=0;v<w-m;v++)o.find("> .siteorigin-widget-field-repeater-add").click();else if(!r&&w<m)for(var h=w;h<m;h++){e(u.eq(h)).find("> .siteorigin-widget-field-repeater-item-top").find(".siteorigin-widget-field-remove").trigger("click",{silent:!0})}u=o.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item");for(var b=0;b<u.length;b++)u.eq(b).find("> .siteorigin-widget-field-repeater-item-form"),s(u.eq(b).find("> .siteorigin-widget-field-repeater-item-form"),l[b])}})),--a):--a};s(i,t),i.find("*[name]").each((function(){var i=e(this),a=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(null==a)return!0;var s=(a=a[1]).split("][");s=s.map((function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e}));for(var o,d=t,l=0;l<s.length;l++){if(!d.hasOwnProperty(s[l])){if(r)return!0;break}l===s.length-1?o=d[s[l]]:d=d[s[l]]}if("checkbox"===i.attr("type"))i.prop("checked",o);else if("radio"===i.attr("type"))i.prop("checked",o===i.val());else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var g=null;"undefined"!=typeof tinyMCE&&(g=tinyMCE.get(i.attr("id"))),null!==g&&"function"==typeof g.setContent&&!g.isHidden()&&i.parent().is(":visible")?g.initialized?g.setContent(o):g.on("init",(function(){g.setContent(o)})):i.val(o)}else if(i.is(".panels-data")){i.val(o);var f=i.data("builder");f&&f.setDataField(i)}else i.val(o);n&&(i.trigger("change"),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})))}))},sowbForms.displayNotice=function(i,t,r,n,a){var s=e('<div class="siteorigin-widget-form-notification"></div>');t&&s.append("<span>"+t+"</span>"),n&&n.length&&n.forEach((function(i){var t="";i.classes&&i.classes.length&&(t=" "+i.classes.join(" "));var r=e('<a class="button button-small'+t+'">'+i.label+"</a>");i.url&&r.attr("href",i.url),i.callback&&r.on("click",(function(){i.callback(s)})),s.append(r)})),r&&s.append("<div><small>"+r+"</small></div>"),a?a.before(s):i.prepend(s)},e(".widgets-holder-wrap").on("click",".widget:has(.siteorigin-widget-form-main) .widget-top",(function(){var i=e(this).closest(".widget").find(".siteorigin-widget-form-main");setTimeout((function(){i.sowSetupForm()}),200)}));var i=e("body");i.hasClass("wp-customizer")&&e(document).on("widget-added",(function(e,i){i.find(".siteorigin-widget-form").sowSetupForm()})),i.hasClass("block-editor-page")&&e(document).on("panels_setup_preview",(function(){window.hasOwnProperty("sowb")&&e(sowb).trigger("setup_widgets",{preview:!0})})),e(document).on("open_dialog",(function(e,i){i.$el.find(".so-panels-dialog").is(".so-panels-dialog-edit-widget")&&i.$el.find(".siteorigin-widget-form-main").find("> .siteorigin-widget-field").trigger("sowsetupformfield")})),e((function(){e(document).trigger("sowadminloaded")}))}(jQuery);var sowEmitters={_match:function(e,i){void 0===i&&(i=".*");var t=new RegExp("^([a-zA-Z0-9_-]+)(\\[([a-zA-Z0-9_-]+)\\])? *: *("+i+") *$").exec(e);if(null===t)return!1;var r="",n="default";return void 0!==t[3]?(n=t[1],r=t[3]):r=t[1],{match:t[4].trim(),group:n,state:r}},_checker:function(e,i,t,r){var n,a={};void 0===i.length&&(i=[i]);for(var s=0;s<i.length;s++)!1!==(n=sowEmitters._match(i[s],t))&&("_true"===n.match||r(e,i,n.match))&&(a[n.group]=n.state);return a},select:function(e,i){void 0===i.length&&(i=[i]);for(var t={},r=0;r<i.length;r++)""===i[r]&&(i[r]="default"),t[i[r]]=e;return t},conditional:function(val,args){return sowEmitters._checker(val,args,"[^;{}]*",(function(val,args,match){return eval(match)}))},in:function(e,i){return sowEmitters._checker(e,i,"[^;{}]*",(function(e,i,t){return-1!==t.split(",").map((function(e){return e.trim()})).indexOf(e)}))}};window.sowbForms=sowbForms;
1
+ var sowbForms=window.sowbForms||{};!function(e){e.fn.sowSetupForm=function(){return e(this).each((function(i,t){var r,n=e(t),a=!0,s=e("body"),o=n.find("input[name]");if(o.length&&-1!==o.attr("name").indexOf("__i__"))return this;if(n.is(".siteorigin-widget-form-main")){if(!0===n.data("sow-form-setup"))return!0;if(s.hasClass("widgets-php")&&!n.is(":visible")&&0===n.closest(".panel-dialog").length)return!0;n.on("sowstatechange",(function(i,t,r){n.find("[data-state-handler]").each((function(){var i,n,s,o,d,l,g=e(this),f=e.extend({},g.data("state-handler"),a?g.data("state-handler-initial"):{});if(0===Object.keys(f).length)return!0;var c={},p=sowbForms.getContainerFieldId(g,"repeater",".siteorigin-widget-field-repeater-item");if(!1!==p){var u={};for(var w in f)u[w.replace("{$repeater}",p)]=f[w];f=u}var m=sowbForms.getContainerFieldId(g,"widget",".siteorigin-widget-widget");if(!1!==m){var v={};for(var h in f){var b=h.match(/_else\[(.*)\]|(.*)\[(.*)\]/);v[b&&b.length&&void 0===b[1]?b[2]+"_"+m+"["+b[3]+"]":"_else["+b[1]+"_"+m+"]"]=f[h]}f=v}for(var y in f)if(d=!1,null!==(i=y.match(/^([a-zA-Z0-9_-]+)(\[([a-zA-Z0-9_\-,]+)\])?(\[\])?$/))){if(n={group:"default",name:"",multi:!1},void 0!==i[2]?(n.group=i[1],n.name=i[3]):n.name=i[0],n.multi=void 0!==i[4],"_else"===n.group)n.group=n.name,n.name="",d=n.group===t&&void 0===c[n.group];else{l=n.name.split(",").map((function(e){return e.trim()}));for(var F=0;F<l.length&&!(d=n.group===t&&l[F]===r);F++);}if(d){s=f[y],n.multi||(s=[s]);for(F=0;F<s.length;F++){if((o=void 0!==s[F][1]&&Boolean(s[F][1])?g.find(s[F][1]):g)[s[F][0]].apply(o,void 0!==s[F][2]?s[F][2]:[]),o.is(".siteorigin-widget-field:visible"))if(o.is(".siteorigin-widget-field-type-section"))o.find("> .siteorigin-widget-section > .siteorigin-widget-field").trigger("sowsetupformfield");else o.trigger("sowsetupformfield")}c[n.group]=!0}}}))})),n.sowSetupPreview(),r=n;var d=n.find(".siteorigin-widget-teaser");if(d.find(".dashicons-dismiss").click((function(){var i=e(this);e.get(i.data("dismiss-url")),d.slideUp("normal",(function(){d.remove()}))})),!n.data("backupDisabled")){var l=n.find("> .siteorigin-widgets-form-id").val(),g=n.find("> .siteorigin-widgets-form-timestamp"),f=parseInt(g.val()||0),c=JSON.parse(sessionStorage.getItem(l));c&&(c._sow_form_timestamp>f?sowbForms.displayNotice(n,soWidgets.backup.newerVersion,soWidgets.backup.replaceWarning,[{label:soWidgets.backup.restore,callback:function(e){sowbForms.setWidgetFormValues(r,c),e.slideUp("fast",(function(){e.remove()}))}},{label:soWidgets.backup.dismiss,callback:function(e){e.slideUp("fast",(function(){sessionStorage.removeItem(l),e.remove()}))}}]):sessionStorage.removeItem(l)),n.change((function(){g.val((new Date).getTime());var e=sowbForms.getWidgetFormValues(n);sessionStorage.setItem(l,JSON.stringify(e))}))}}else r=n.closest(".siteorigin-widget-form-main");r.find("> .siteorigin-widgets-form-id").val();var p=n.find("> .siteorigin-widget-field");p.find("> .siteorigin-widget-section").sowSetupForm();var u=p.find("> .siteorigin-widget-widget");u.find("> .siteorigin-widget-section").sowSetupForm(),u.filter(":not(:has(> .siteorigin-widget-section))").sowSetupForm(),p.find(".siteorigin-widget-input").each((function(i,t){null===e(t).data("original-name")&&e(t).data("original-name",e(t).attr("name"))})),p.find("> .siteorigin-widget-field-repeater").sowSetupRepeater(),n.find(".siteorigin-widget-field-repeater-item").sowSetupRepeaterItems(),p.find("> .siteorigin-widget-input-color").each((function(){var i=e(this),t={change:function(i,t){setTimeout((function(){e(i.target).trigger("change")}),100)}};i.data("defaultColor")&&(t.defaultColor=i.data("defaultColor")),i.wpColorPicker(t)}));var w=function(){e(this).toggleClass("siteorigin-widget-section-visible"),e(this).parent().find("> .siteorigin-widget-section, > .siteorigin-widget-widget > .siteorigin-widget-section").slideToggle("fast",(function(){(e(window).resize(),e(this).find("> .siteorigin-widget-field-container-state").val(e(this).is(":visible")?"open":"closed"),e(this).is(":visible"))&&e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")}))};p.filter(".siteorigin-widget-field-type-widget, .siteorigin-widget-field-type-section").find("> label").click(w),p.filter(".siteorigin-widget-field-type-posts").find(".posts-container-label-wrapper").click(w),p.filter(".siteorigin-widget-field-type-slider").each((function(){var i=e(this),t=i.find('input[type="number"]'),r=i.find(".siteorigin-widget-value-slider");r.slider({max:parseFloat(t.attr("max")),min:parseFloat(t.attr("min")),step:parseFloat(t.attr("step")),value:parseFloat(t.val()),slide:function(e,r){t.val(parseFloat(r.value)),t.trigger("change"),i.find(".siteorigin-widget-slider-value").html(r.value)}}),t.change((function(e,i){i&&i.silent||r.slider("value",parseFloat(t.val()))}))})),p.filter(".siteorigin-widget-field-type-link").each((function(){var i=e(this),t=function(){var t=i.find(".content-text-search"),r=t.val(),n=t.data("postTypes"),a=i.find("ul.posts").empty().addClass("loading");e.get(soWidgets.ajaxurl,{action:"so_widgets_search_posts",query:r,postTypes:n},(function(i){for(var t=0;t<i.length;t++)""===i[t].label&&(i[t].label="&nbsp;"),a.append(e("<li>").addClass("post").html(i[t].label+"<span>("+i[t].type+")</span>").data(i[t]));a.removeClass("loading")}))};i.find(".select-content-button, .button-close").click((function(r){r.preventDefault(),e(this).blur();var n=i.find(".existing-content-selector");n.toggle(),n.is(":visible")&&0===n.find("ul.posts li").length&&t()})),i.on("click",".posts li",(function(t){t.preventDefault();var r=e(this);i.find("input.siteorigin-widget-input").val("post: "+r.data("value")),i.change(),i.find(".existing-content-selector").toggle()}));var r=null;i.find(".content-text-search").keyup((function(){null!==r&&clearTimeout(r),r=setTimeout((function(){t()}),500)}))})),void 0!==jQuery.fn.soPanelsSetupBuilderWidget&&p.filter(".siteorigin-widget-field-type-builder").each((function(){e(this).find("> .siteorigin-page-builder-field").each((function(){var i=e(this);i.soPanelsSetupBuilderWidget({builderType:i.data("type")})}))}));var m=function(){var i=e(this),t=i.closest("[data-state-emitter]").data("state-emitter");if(void 0!==t){var n=function(t,r){if(void 0===sowEmitters[t.callback]||"_"===t.callback.substr(0,1))return r;if(i.is('[type="radio"]')&&!i.is(":checked"))return r;var n=sowbForms.getContainerFieldId(i,"repeater",".siteorigin-widget-field-repeater-item");!1!==n&&(t.args=t.args.map((function(e){return e.replace("{$repeater}",n)})));var a=sowbForms.getContainerFieldId(i,"widget",".siteorigin-widget-widget");!1===a||t.hasOwnProperty("widgetFieldId")||(t.widgetFieldId=a,t.args=t.args.map((function(e){return e="conditional"===t.callback?e.replace(/(.*)(\[.*)/,"$1_"+a+"$2"):e+"_"+a})));var s=i.is('[type="checkbox"]')?i.is(":checked"):i.val();return e.extend(r,sowEmitters[t.callback](s,t.args))},a={default:""};void 0===t.length&&(t=[t]);for(var s=0;s<t.length;s++)a=n(t[s],a);var o=r.data("states");for(var d in void 0===o&&(o={default:""}),a)void 0!==o[d]&&a[d]===o[d]||(o[d]=a[d],r.trigger("sowstatechange",[d,a[d]]));r.data("states",o)}};p.filter("[data-state-emitter]").each((function(){var i=e(this).find(".siteorigin-widget-input");i.on("keyup change",m),i.each((function(){var i=e(this);i.is(":radio")?i.is(":checked")&&m.call(i[0]):m.call(i[0])}))})),n.trigger("sowsetupform",p).data("sow-form-setup",!0),p.trigger("sowsetupformfield"),n.find(".siteorigin-widget-field-repeater-item").trigger("updateFieldPositions"),(s.hasClass("wp-customizer")||s.hasClass("widgets-php"))&&n.closest(".ui-sortable").on("sortstop",(function(e,i){i.item.find(".siteorigin-widget-form").find("> .siteorigin-widget-field").trigger("sowsetupformfield")})),a=!1}))},e.fn.sowSetupPreview=function(){var i=e(this);i.siblings(".siteorigin-widget-preview").find("> a").click((function(t){t.preventDefault();var r=sowbForms.getWidgetFormValues(i),n=e(e("#so-widgets-bundle-tpl-preview-dialog").html().trim()).appendTo("body");n.find('input[name="data"]').val(JSON.stringify(r)),n.find('input[name="class"]').val(i.data("class")),n.find("iframe").on("load",(function(){e(this).css("visibility","visible")})),n.find("form").submit(),n.find(".close").click((function(){n.remove()}))}))},e.fn.sowSetupRepeater=function(){return e(this).each((function(i,t){var r=e(t),n=r.find(".siteorigin-widget-field-repeater-items"),a=r.data("repeater-name");n.bind("updateFieldPositions",(function(){var i=e(this),t=i.find("> .siteorigin-widget-field-repeater-item");t.each((function(i,t){e(t).find(".siteorigin-widget-input").each((function(t,r){var n=e(r).data("repeater-positions");void 0===n&&(n={}),n[a]=i,e(r).data("repeater-positions",n)}))})),i.find(".siteorigin-widget-input").each((function(i,t){var r=e(t),n=r.data("repeater-positions");if(void 0!==n){var a=r.attr("data-original-name");if(a||(r.attr("data-original-name",r.attr("name")),a=r.attr("name")),!a)return;if(n)for(var s in n)a=a.replace("#"+s+"#",n[s]);r.attr("name",a)}})),i.data("initialSetup")||(i.find(".siteorigin-widget-input").each((function(i,t){var r=e(t);r.prop("checked",r.prop("defaultChecked"))})),i.data("initialSetup",!0));var n=r.data("scroll-count")?parseInt(r.data("scroll-count")):0;if(n>0&&t.length>n){var s=t.first().outerHeight();i.css("max-height",s*n).css("overflow","auto")}else i.css("max-height","").css("overflow","")})),n.sortable({handle:".siteorigin-widget-field-repeater-item-top",items:"> .siteorigin-widget-field-repeater-item",update:function(){n.find('input[type="radio"].siteorigin-widget-input').attr("name",""),n.trigger("updateFieldPositions"),r.trigger("change")},sortstop:function(i,t){t.item.is(".siteorigin-widget-field-repeater-item")?t.item.find("> .siteorigin-widget-field-repeater-item-form").each((function(){e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")})):t.item.find(".siteorigin-widget-form").find("> .siteorigin-widget-field").trigger("sowsetupformfield");r.trigger("change")}}),n.trigger("updateFieldPositions"),r.find("> .siteorigin-widget-field-repeater-add").disableSelection().click((function(i){i.preventDefault(),r.closest(".siteorigin-widget-field-repeater").sowAddRepeaterItem().find("> .siteorigin-widget-field-repeater-items").slideDown("fast",(function(){e(window).resize()}))})),r.find("> .siteorigin-widget-field-repeater-top > .siteorigin-widget-field-repeater-expand").click((function(i){i.preventDefault(),r.closest(".siteorigin-widget-field-repeater").find("> .siteorigin-widget-field-repeateritems-").slideToggle("fast",(function(){e(window).resize()}))}))}))},e.fn.sowAddRepeaterItem=function(){return e(this).each((function(i,t){var r=e(t),n=r.find("> .siteorigin-widget-field-repeater-items").children().length+1,a=e("<div>"+r.find("> .siteorigin-widget-field-repeater-item-html").html()+"</div>");a.find(".siteorigin-widget-input[data-name]").each((function(){var i=e(this);0===i.closest(".siteorigin-widget-field-repeater-item-html").length&&i.attr("name",e(this).data("name"))}));var s="";a.find("> .siteorigin-widget-field").each((function(i,t){var r=t.outerHTML;e(t).is(".siteorigin-widget-field-type-repeater")||(r=r.replace(/_id_/g,n)),s+=r}));var o=void 0!==r.attr("readonly"),d=e('<div class="siteorigin-widget-field-repeater-item ui-draggable" />').append(e('<div class="siteorigin-widget-field-repeater-item-top" />').append(e('<div class="siteorigin-widget-field-expand" />')).append(o?"":e('<div class="siteorigin-widget-field-copy" />')).append(o?"":e('<div class="siteorigin-widget-field-remove" />')).append(e("<h4 />").html(r.data("item-name")))).append(e('<div class="siteorigin-widget-field-repeater-item-form" />').html(s));r.find("> .siteorigin-widget-field-repeater-items").append(d).sortable("refresh").trigger("updateFieldPositions"),d.sowSetupRepeaterItems(),d.hide().slideDown("fast",(function(){e(window).resize()})),r.trigger("change")}))},e.fn.sowRemoveRepeaterItem=function(){return e(this).each((function(i,t){var r=e(this).closest(".siteorigin-widget-field-repeater-items");e(this).remove(),r.sortable("refresh").trigger("updateFieldPositions"),e(t).trigger("change")}))},e.fn.sowSetupRepeaterItems=function(){return e(this).each((function(i,t){var r=e(t);if(void 0===r.data("sowrepeater-actions-setup")){var n=r.closest(".siteorigin-widget-field-repeater"),a=r.find("> .siteorigin-widget-field-repeater-item-top"),s=n.data("item-label"),o=r.parents(".siteorigin-widget-field-repeater").data("item-name");if(s&&(s.hasOwnProperty("selector")||s.hasOwnProperty("selectorArray"))){var d=function(){var e,i,t;if(s.hasOwnProperty("selectorArray"))for(var n=0;n<s.selectorArray.length&&(e=(t=s.selectorArray[n]).hasOwnProperty("valueMethod")&&t.valueMethod?t.valueMethod:"val",!(i=r.find(t.selector)[e]()));n++);else e=s.hasOwnProperty("valueMethod")&&s.valueMethod?s.valueMethod:"val",i=r.find(s.selector)[e]();i?(i.length>80&&(i=i.substr(0,79)+"..."),a.find("h4").text(i)):a.find("h4").text(o)};d();var l=s.hasOwnProperty("updateEvent")&&s.updateEvent?s.updateEvent:"change";r.bind(l,d)}a.click((function(i){"siteorigin-widget-field-remove"!==i.target.className&&"siteorigin-widget-field-copy"!==i.target.className&&(i.preventDefault(),e(this).closest(".siteorigin-widget-field-repeater-item").find(".siteorigin-widget-field-repeater-item-form").eq(0).slideToggle("fast",(function(){e(window).resize(),e(this).is(":visible")?(e(this).trigger("slideToggleOpenComplete"),e(this).find(".siteorigin-widget-field-type-section > .siteorigin-widget-section > .siteorigin-widget-field,> .siteorigin-widget-field").each((function(i,t){var r=e(t);r.is(":visible")&&r.trigger("sowsetupformfield")}))):e(this).trigger("slideToggleCloseComplete")})))})),a.find(".siteorigin-widget-field-remove").click((function(i,t){i.preventDefault();var r=e(this).closest(".siteorigin-widget-field-repeater-items"),a=e(this).closest(".siteorigin-widget-field-repeater-item"),s=function(){a.remove(),r.sortable("refresh").trigger("updateFieldPositions"),e(window).resize(),n.trigger("change")};t&&t.silent?s():confirm(soWidgets.sure)&&a.slideUp("fast",s)})),a.find(".siteorigin-widget-field-copy").click((function(i){i.preventDefault();var t=e(this).closest(".siteorigin-widget-form-main"),n=e(this).closest(".siteorigin-widget-field-repeater-item"),a=n.clone(),s=n.closest(".siteorigin-widget-field-repeater-items"),o=s.children().length,d={};a.find("*[name]").each((function(){var i=e(this),s=i.attr("id"),l=i.attr("name");if(i.is("textarea")&&i.parent().is(".wp-editor-container")&&"undefined"!=typeof tinymce){i.parent().empty().append(i),i.css("display","");var g=tinymce.get(s);g&&i.val(g.getContent())}else if(i.is(".wp-color-picker")){var f=i.closest(".wp-picker-container"),c=i.closest(".siteorigin-widget-field");f.remove(),c.append(i.remove())}else{var p=s?n.find("#"+s):n.find('[name="'+l+'"]');p.length&&null!=p.val()&&i.val(p.val())}if(s){var u,w;if(i.is('[type="radio"]')){u=s.replace(/-\d+-\d+$/,"");var m=s.replace(/-\d+$/,"");if(!d[u]){var v={};d[u]=t.find(".siteorigin-widget-input[id^="+u+"]").not("[id*=_id_]").filter((function(i,t){var r=e(t).attr("name");return!v[r]&&(v[r]=!0,!0)})).length+1}var h=u+"-"+d[u];w=h+s.match(/-\d+$/)[0],a.find("label[for="+m+"]").attr("for",h)}else F=new RegExp("-\\d+$"),u=s.replace(F,""),d[u]||(d[u]=t.find(".siteorigin-widget-input[id^="+u+"]").not("[id*=_id_]").length+1),w=u+"-"+d[u]++;if(i.attr("id",w),i.is(".wp-editor-area")){var b=i.closest(".siteorigin-widget-tinymce-container"),y=b.data("media-buttons");if(y&&y.html){var F=new RegExp(s,"g");y.html=y.html.replace(F,w),b.data("media-buttons",y)}}a.find("label[for="+s+"]").attr("for",w),a.find("[id*="+s+"]").each((function(){var i=e(this).attr("id").replace(s,w);e(this).attr("id",i)})),"undefined"!=typeof tinymce&&tinymce.get(w)&&tinymce.get(w).remove()}var k=n.parents(".siteorigin-widget-field-repeater").length,_=e("body");(_.hasClass("wp-customizer")||_.hasClass("widgets-php"))&&0===r.closest(".panel-dialog").length&&(k+=1);var C=l.replace(new RegExp("((?:.*?\\[\\d+\\]){"+(k-1).toString()+"})?(.*?\\[)\\d+(\\])"),"$1$2"+o.toString()+"$3");i.attr("name",C),i.data("original-name",C)})),s.append(a).sortable("refresh").trigger("updateFieldPositions"),a.sowSetupRepeaterItems(),a.hide().slideDown("fast",(function(){e(window).resize()})),r.trigger("change")})),r.find("> .siteorigin-widget-field-repeater-item-form").sowSetupForm(),r.data("sowrepeater-actions-setup",!0)}}))},sowbForms.getContainerFieldId=function(e,i,t){var r=i+"FieldId";this.hasOwnProperty(r)||(this[r]=1);var n=e.closest(t);if(n.length){var a=n.data("field-id");return void 0===a&&(a=this[r]++),n.data("field-id",a),a}return!1},sowbForms.getWidgetFieldVariable=function(e,i,t){var r=window.sow_field_javascript_variables[e];i=i.replace(/\[#.*?#\]/g,"");for(var n=/[a-zA-Z0-9\-]+(?:\[c?[0-9]+\])?\[(.*)\]/.exec(i)[1].split("]["),a=n.length?r:null;n.length;)a=a[n.shift()];return a[t]},sowbForms.fetchWidgetVariable=function(i,t,r){window.sowVars=window.sowVars||{},void 0===window.sowVars[t]?e.post(soWidgets.ajaxurl,{action:"sow_get_javascript_variables",widget:t,key:i},(function(e){window.sowVars[t]=e,r(window.sowVars[t][i])})):r(window.sowVars[t][i])},sowbForms.getWidgetIdBase=function(e){return e.data("id-base")},sowbForms.getWidgetFormValues=function(i){if(_.isUndefined(i))return null;var t={};return i.find("*[name]").each((function(){var i=e(this);try{var r=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(_.isEmpty(r))return!0;var n=(r=r[1]).split("][");n=n.map((function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e}));var a=t,s=null,o=_.isString(i.attr("type"))?i.attr("type").toLowerCase():null;if("checkbox"===o)s=!!i.is(":checked")&&(""===i.val()||i.val());else if("radio"===o){if(!i.is(":checked"))return;s=i.val()}else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var d=null;"undefined"!=typeof tinyMCE&&(d=tinyMCE.get(i.attr("id"))),s=null===d||"function"!=typeof d.getContent||d.isHidden()?i.val():d.getContent()}else if("SELECT"===i.prop("tagName")){var l=i.find("option:selected");1===l.length?s=i.find("option:selected").val():l.length>1&&(s=_.map(i.find("option:selected"),(function(i,t){return e(i).val()})))}else s=i.val();for(var g=0;g<n.length;g++)g===n.length-1?""===n[g]?a.push(s):a[n[g]]=s:(_.isUndefined(a[n[g]])&&(_.isNumber(n[g+1])||""===n[g+1]?a[n[g]]=[]:a[n[g]]={}),a=a[n[g]])}catch(e){console.error("Field ["+i.attr("name")+"] could not be processed and was skipped - "+e.message)}})),t},sowbForms.setWidgetFormValues=function(i,t,r,n){r=r||!1,n=void 0!==n&&n||void 0===n;var a=0,s=function(i,t){10!=++a?(i.find("> .siteorigin-widget-field-type-repeater,> .siteorigin-widget-field-type-section > .siteorigin-widget-section > .siteorigin-widget-field-type-repeater").each((function(i,n){var a=e(this),o=a.find("> .siteorigin-widget-field-repeater"),d=o.data("repeaterName"),l=t.hasOwnProperty(d)?t[d]:null;if(a.parent().is(".siteorigin-widget-section")){var g=o.data("element-name");g=g.replace(/\[#.*?#\]/g,"");for(var f=/[a-zA-Z0-9\-]+(?:\[c?[0-9]+\])?\[(.*)\]/.exec(g)[1].split("]["),c=f.length?t:null;f.length;){var p=f.shift();c=c.hasOwnProperty(p)?c[p]:c}l=c}if(l&&Array.isArray(l)){var u=o.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item"),w=l.length,m=u.length;if(w>m)for(var v=0;v<w-m;v++)o.find("> .siteorigin-widget-field-repeater-add").click();else if(!r&&w<m)for(var h=w;h<m;h++){e(u.eq(h)).find("> .siteorigin-widget-field-repeater-item-top").find(".siteorigin-widget-field-remove").trigger("click",{silent:!0})}u=o.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item");for(var b=0;b<u.length;b++)u.eq(b).find("> .siteorigin-widget-field-repeater-item-form"),s(u.eq(b).find("> .siteorigin-widget-field-repeater-item-form"),l[b])}})),--a):--a};s(i,t),i.find("*[name]").each((function(){var i=e(this),a=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(null==a)return!0;var s=(a=a[1]).split("][");s=s.map((function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e}));for(var o,d=t,l=0;l<s.length;l++){if(!d.hasOwnProperty(s[l])){if(r)return!0;break}l===s.length-1?o=d[s[l]]:d=d[s[l]]}if("checkbox"===i.attr("type"))i.prop("checked",o);else if("radio"===i.attr("type"))i.prop("checked",o===i.val());else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var g=null;"undefined"!=typeof tinyMCE&&(g=tinyMCE.get(i.attr("id"))),null!==g&&"function"==typeof g.setContent&&!g.isHidden()&&i.parent().is(":visible")?g.initialized?g.setContent(o):g.on("init",(function(){g.setContent(o)})):i.val(o)}else if(i.is(".panels-data")){i.val(o);var f=i.data("builder");f&&f.setDataField(i)}else i.val(o);n&&(i.trigger("change"),this.dispatchEvent(new Event("change",{bubbles:!0,cancelable:!0})))}))},sowbForms.displayNotice=function(i,t,r,n,a){var s=e('<div class="siteorigin-widget-form-notification"></div>');t&&s.append("<span>"+t+"</span>"),n&&n.length&&n.forEach((function(i){var t="";i.classes&&i.classes.length&&(t=" "+i.classes.join(" "));var r=e('<a class="button button-small'+t+'">'+i.label+"</a>");i.url&&r.attr("href",i.url),i.callback&&r.on("click",(function(){i.callback(s)})),s.append(r)})),r&&s.append("<div><small>"+r+"</small></div>"),a?a.before(s):i.prepend(s)},e(".widgets-holder-wrap").on("click",".widget:has(.siteorigin-widget-form-main) .widget-top",(function(){var i=e(this).closest(".widget").find(".siteorigin-widget-form-main");setTimeout((function(){i.sowSetupForm()}),200)}));var i=e("body");i.hasClass("wp-customizer")&&e(document).on("widget-added",(function(e,i){i.find(".siteorigin-widget-form").sowSetupForm()})),i.hasClass("block-editor-page")&&e(document).on("panels_setup_preview",(function(){window.hasOwnProperty("sowb")&&e(sowb).trigger("setup_widgets",{preview:!0})})),e(document).on("open_dialog",(function(e,i){i.$el.find(".so-panels-dialog").is(".so-panels-dialog-edit-widget")&&i.$el.find(".siteorigin-widget-form-main").find("> .siteorigin-widget-field").trigger("sowsetupformfield")})),e((function(){e(document).trigger("sowadminloaded")}))}(jQuery);var sowEmitters={_match:function(e,i){void 0===i&&(i=".*");var t=new RegExp("^([a-zA-Z0-9_-]+)(\\[([a-zA-Z0-9_-]+)\\])? *: *("+i+") *$").exec(e);if(null===t)return!1;var r="",n="default";return void 0!==t[3]?(n=t[1],r=t[3]):r=t[1],{match:t[4].trim(),group:n,state:r}},_checker:function(e,i,t,r){var n,a={};void 0===i.length&&(i=[i]);for(var s=0;s<i.length;s++)!1!==(n=sowEmitters._match(i[s],t))&&("_true"===n.match||r(e,i,n.match))&&(a[n.group]=n.state);return a},select:function(e,i){void 0===i.length&&(i=[i]);for(var t={},r=0;r<i.length;r++)""===i[r]&&(i[r]="default"),t[i[r]]=e;return t},conditional:function(val,args){return sowEmitters._checker(val,args,"[^;{}]*",(function(val,args,match){return eval(match)}))},in:function(e,i){return sowEmitters._checker(e,i,"[^;{}]*",(function(e,i,t){return-1!==t.split(",").map((function(e){return e.trim()})).indexOf(e)}))}};window.sowbForms=sowbForms;
css/slider/slider.css CHANGED
@@ -1 +1 @@
1
- @font-face{font-family:'so-slider-pointers';src:url('fonts/slider.eot?8p86w5');src:url('fonts/slider.eot?#iefix8p86w5') format('embedded-opentype'),url('fonts/slider.woff?8p86w5') format('woff'),url('fonts/slider.ttf?8p86w5') format('truetype'),url('fonts/slider.svg?8p86w5#slider') format('svg');font-weight:normal;font-style:normal}.sow-slider-base{position:relative;overflow:hidden}.sow-slider-base ul.sow-slider-images{list-style:none;margin:0;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image{width:100%;margin:0;list-style:none;position:relative;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image.sow-slider-image-cover{background-position:center center;background-size:cover}.sow-slider-base ul.sow-slider-images li.sow-slider-image.sow-slider-image-cover{background-repeat:repeat}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container{position:absolute;top:0;left:0;width:100%;z-index:2}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper{margin:0 auto;z-index:2;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper>*:first-child{margin-top:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper>*:last-child{margin-bottom:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay{position:absolute;top:0;left:0;bottom:0;right:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay.sow-slider-image-cover{background-position:center center;background-size:cover}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay.sow-slider-image-cover{background-repeat:repeat}.sow-slider-base ul.sow-slider-images li.sow-slider-image>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image>a>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-wrapper>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-wrapper>a>img{display:block;width:100%;height:auto;border:none}.sow-slider-base ul.sow-slider-images li.sow-slider-image video.sow-background-element{position:absolute;top:50%;left:50%;width:auto;height:auto;z-index:1;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image video.sow-full-element{display:block;width:100%;height:auto}.sow-slider-base .sow-slider-pagination{list-style:none;margin:0;text-align:right;position:absolute;bottom:20px;left:0;width:100%;z-index:1001;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;padding-right:30px;line-height:11px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.sow-slider-base .sow-slider-pagination li{text-align:left;margin:0;display:inline-block}.sow-slider-base .sow-slider-pagination li a{display:block;text-indent:-9999px;width:11px;height:11px;background:#FFFFFF;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;opacity:.45}.sow-slider-base .sow-slider-pagination li.sow-active a{opacity:.85}.sow-slider-base .sow-slide-nav{list-style:none;z-index:1001;position:absolute;top:50%;transform:translateY(-50%);opacity:.75;font-size:25px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.sow-slider-base .sow-slide-nav a{display:block;padding:15px;text-align:center;text-decoration:none;color:#FFFFFF}.sow-slider-base .sow-slide-nav a em{display:block}.sow-slider-base .sow-slide-nav.sow-slide-nav-next{right:5px}.sow-slider-base .sow-slide-nav.sow-slide-nav-next a{background-position:top right}.sow-slider-base .sow-slide-nav.sow-slide-nav-prev{left:5px}.sow-slider-base .sow-slide-nav.sow-slide-nav-prev a{background-position:top left}.sow-slider-base .cycle-sentinal{overflow:hidden}.sow-slider-base.sow-slider-is-mobile video.sow-background-element:not(.sow-mobile-video_enabled){visibility:hidden}.sow-slider-base [class^="sow-sld-icon-"],.sow-slider-base [class*=" sow-sld-icon-"]{font-family:'so-slider-pointers';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sow-slider-base .sow-sld-icon-ultra-thin-rounded-left:before{content:"\e600"}.sow-slider-base .sow-sld-icon-ultra-thin-rounded-right:before{content:"\e601"}.sow-slider-base .sow-sld-icon-thin-rounded-left:before{content:"\e602"}.sow-slider-base .sow-sld-icon-thin-rounded-right:before{content:"\e603"}.sow-slider-base .sow-sld-icon-medium-rounded-left:before{content:"\e604"}.sow-slider-base .sow-sld-icon-medium-rounded-right:before{content:"\e605"}.sow-slider-base .sow-sld-icon-thick-rounded-left:before{content:"\e606"}.sow-slider-base .sow-sld-icon-thick-rounded-right:before{content:"\e607"}.sow-slider-base .sow-sld-icon-ultra-thin-left:before{content:"\e608"}.sow-slider-base .sow-sld-icon-ultra-thin-right:before{content:"\e609"}.sow-slider-base .sow-sld-icon-thin-left:before{content:"\e60a"}.sow-slider-base .sow-sld-icon-thin-right:before{content:"\e60b"}.sow-slider-base .sow-sld-icon-medium-left:before{content:"\e60c"}.sow-slider-base .sow-sld-icon-medium-right:before{content:"\e60d"}.sow-slider-base .sow-sld-icon-thick-left:before{content:"\e60e"}.sow-slider-base .sow-sld-icon-thick-right:before{content:"\e60f"}
1
+ @font-face{font-family:'so-slider-pointers';src:url('fonts/slider.eot?8p86w5');src:url('fonts/slider.eot?#iefix8p86w5') format('embedded-opentype'),url('fonts/slider.woff?8p86w5') format('woff'),url('fonts/slider.ttf?8p86w5') format('truetype'),url('fonts/slider.svg?8p86w5#slider') format('svg');font-weight:normal;font-style:normal}.sow-slider-base{position:relative;overflow:hidden}.sow-slider-base ul.sow-slider-images{list-style:none;margin:0;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image{width:100%;margin:0;list-style:none;position:relative;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image.sow-slider-image-cover{background-position:center center;background-size:cover}.sow-slider-base ul.sow-slider-images li.sow-slider-image.sow-slider-image-cover{background-repeat:repeat}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container{position:absolute;top:0;left:0;width:100%;z-index:2}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper{margin:0 auto;z-index:2;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper>*:first-child{margin-top:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-container .sow-slider-image-wrapper>*:last-child{margin-bottom:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay{position:absolute;top:0;left:0;bottom:0;right:0}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay.sow-slider-image-cover{background-position:center center;background-size:cover}.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-overlay.sow-slider-image-cover{background-repeat:repeat}.sow-slider-base ul.sow-slider-images li.sow-slider-image>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image>a>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-wrapper>img,.sow-slider-base ul.sow-slider-images li.sow-slider-image .sow-slider-image-wrapper>a>img{display:block;width:100%;height:auto;border:none}.sow-slider-base ul.sow-slider-images li.sow-slider-image video.sow-background-element{position:absolute;top:50%;left:50%;width:auto;height:auto;z-index:1;overflow:hidden}.sow-slider-base ul.sow-slider-images li.sow-slider-image video.sow-full-element{display:block;width:100%;height:auto}.sow-slider-base .sow-slider-pagination{bottom:20px;-ms-box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;font-size:0;list-style:none;left:0;line-height:11px;margin:0;padding-right:30px;position:absolute;text-align:right;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%;z-index:1001}.sow-slider-base .sow-slider-pagination li{display:inline-block;font-size:1em;text-align:left;margin:0 4px 0 0}.sow-slider-base .sow-slider-pagination li:last-of-type{margin-right:0}.sow-slider-base .sow-slider-pagination li a{background:#fff;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;display:block;height:11px;opacity:.45;text-indent:-9999px;width:11px}.sow-slider-base .sow-slider-pagination li.sow-active a{opacity:.85}.sow-slider-base .sow-slide-nav{list-style:none;z-index:1001;position:absolute;top:50%;transform:translateY(-50%);opacity:.75;font-size:25px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.sow-slider-base .sow-slide-nav a{display:block;padding:15px;text-align:center;text-decoration:none;color:#FFFFFF}.sow-slider-base .sow-slide-nav a em{display:block}.sow-slider-base .sow-slide-nav.sow-slide-nav-next{right:5px}.sow-slider-base .sow-slide-nav.sow-slide-nav-next a{background-position:top right}.sow-slider-base .sow-slide-nav.sow-slide-nav-prev{left:5px}.sow-slider-base .sow-slide-nav.sow-slide-nav-prev a{background-position:top left}.sow-slider-base .cycle-sentinal{overflow:hidden}.sow-slider-base.sow-slider-is-mobile video.sow-background-element:not(.sow-mobile-video_enabled){visibility:hidden}.sow-slider-base [class^="sow-sld-icon-"],.sow-slider-base [class*=" sow-sld-icon-"]{font-family:'so-slider-pointers';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sow-slider-base .sow-sld-icon-ultra-thin-rounded-left:before{content:"\e600"}.sow-slider-base .sow-sld-icon-ultra-thin-rounded-right:before{content:"\e601"}.sow-slider-base .sow-sld-icon-thin-rounded-left:before{content:"\e602"}.sow-slider-base .sow-sld-icon-thin-rounded-right:before{content:"\e603"}.sow-slider-base .sow-sld-icon-medium-rounded-left:before{content:"\e604"}.sow-slider-base .sow-sld-icon-medium-rounded-right:before{content:"\e605"}.sow-slider-base .sow-sld-icon-thick-rounded-left:before{content:"\e606"}.sow-slider-base .sow-sld-icon-thick-rounded-right:before{content:"\e607"}.sow-slider-base .sow-sld-icon-ultra-thin-left:before{content:"\e608"}.sow-slider-base .sow-sld-icon-ultra-thin-right:before{content:"\e609"}.sow-slider-base .sow-sld-icon-thin-left:before{content:"\e60a"}.sow-slider-base .sow-sld-icon-thin-right:before{content:"\e60b"}.sow-slider-base .sow-sld-icon-medium-left:before{content:"\e60c"}.sow-slider-base .sow-sld-icon-medium-right:before{content:"\e60d"}.sow-slider-base .sow-sld-icon-thick-left:before{content:"\e60e"}.sow-slider-base .sow-sld-icon-thick-right:before{content:"\e60f"}
icons/fontawesome/filter.php CHANGED
@@ -1373,9 +1373,9 @@ add_filter('siteorigin_widgets_icons_fontawesome', 'siteorigin_widgets_icons_fon
1373
 
1374
  function siteorigin_widgets_icon_styles_fontawesome_filter( $styles ) {
1375
  return array_merge( $styles, array(
1376
- 'sow-fab' => __( 'Brands', 'so-widgets-bundle' ),
1377
  'sow-far' => __( 'Regular', 'so-widgets-bundle' ),
1378
  'sow-fas' => __( 'Solid', 'so-widgets-bundle' ),
 
1379
  ) );
1380
  }
1381
 
1373
 
1374
  function siteorigin_widgets_icon_styles_fontawesome_filter( $styles ) {
1375
  return array_merge( $styles, array(
 
1376
  'sow-far' => __( 'Regular', 'so-widgets-bundle' ),
1377
  'sow-fas' => __( 'Solid', 'so-widgets-bundle' ),
1378
+ 'sow-fab' => __( 'Brands', 'so-widgets-bundle' ),
1379
  ) );
1380
  }
1381
 
icons/icons.php CHANGED
@@ -4,8 +4,8 @@ define( 'SITEORIGIN_WIDGETS_ICONS', true );
4
 
5
  function siteorigin_widgets_icon_families_filter( $families ){
6
  $bundled = array(
7
- 'elegantline' => __( 'Elegant Themes Line Icons', 'so-widgets-bundle' ),
8
  'fontawesome' => __( 'Font Awesome', 'so-widgets-bundle' ),
 
9
  'genericons' => __( 'Genericons', 'so-widgets-bundle' ),
10
  'icomoon' => __( 'Icomoon Free', 'so-widgets-bundle' ),
11
  'typicons' => __( 'Typicons', 'so-widgets-bundle' ),
4
 
5
  function siteorigin_widgets_icon_families_filter( $families ){
6
  $bundled = array(
 
7
  'fontawesome' => __( 'Font Awesome', 'so-widgets-bundle' ),
8
+ 'elegantline' => __( 'Elegant Themes Line Icons', 'so-widgets-bundle' ),
9
  'genericons' => __( 'Genericons', 'so-widgets-bundle' ),
10
  'icomoon' => __( 'Icomoon Free', 'so-widgets-bundle' ),
11
  'typicons' => __( 'Typicons', 'so-widgets-bundle' ),
js/jquery.touchSwipe.js CHANGED
@@ -1,12 +1,12 @@
1
- /*
2
  * @fileOverview TouchSwipe - jQuery Plugin
3
- * @version 1.6.6
4
  *
5
  * @author Matt Bryson http://www.github.com/mattbryson
6
  * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
7
  * @see http://labs.rampinteractive.co.uk/touchSwipe/
8
  * @see http://plugins.jquery.com/project/touchSwipe
9
- *
10
  * Copyright (c) 2010-2015 Matt Bryson
11
  * Dual licensed under the MIT or GPL Version 2 licenses.
12
  *
@@ -55,13 +55,13 @@
55
  * - Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
56
  *
57
  * $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
58
- * $version: 1.3.3 - Code tidy prep for minefied version
59
  *
60
  * $Date: 2012-04-10 (wed, 4 Oct 2012) $
61
  * $version: 1.4.0 - Added pinch support, pinchIn and pinchOut
62
  *
63
  * $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
64
- * $version: 1.5.0 - Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is one select that removes all form, input select, button and anchor elements.
65
  *
66
  * $Date: 2012-22-10 (Mon, 22 Oct 2012) $
67
  * $version: 1.5.1 - Fixed bug with jQuery 1.8 and trailing comma in excludedElements
@@ -101,8 +101,36 @@
101
  * $version 1.6.7 - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
102
  *
103
  * $Date: 2015-2-2 (Mon, 2 Feb 2015) $
104
- * $version 1.6.7 - Added preventDefaultEvents option to proxy events regardless.
105
  * - Fixed issue with swipe and pinch not triggering at the same time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  */
107
 
108
  /**
@@ -123,1935 +151,1962 @@
123
  */
124
 
125
 
126
-
127
- (function (factory) {
128
- if (typeof define === 'function' && define.amd && define.amd.jQuery) {
129
- // AMD. Register as anonymous module.
130
- define(['jquery.touchSwipe.js'], factory);
131
- } else {
132
- // Browser globals.
133
- factory(jQuery);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
- }(function ($) {
136
- "use strict";
137
-
138
- //Constants
139
- var LEFT = "left",
140
- RIGHT = "right",
141
- UP = "up",
142
- DOWN = "down",
143
- IN = "in",
144
- OUT = "out",
145
-
146
- NONE = "none",
147
- AUTO = "auto",
148
-
149
- SWIPE = "swipe",
150
- PINCH = "pinch",
151
- TAP = "tap",
152
- DOUBLE_TAP = "doubletap",
153
- LONG_TAP = "longtap",
154
- HOLD = "hold",
155
 
156
- HORIZONTAL = "horizontal",
157
- VERTICAL = "vertical",
158
-
159
- ALL_FINGERS = "all",
160
-
161
- DOUBLE_TAP_THRESHOLD = 10,
162
-
163
- PHASE_START = "start",
164
- PHASE_MOVE = "move",
165
- PHASE_END = "end",
166
- PHASE_CANCEL = "cancel",
167
-
168
- SUPPORTS_TOUCH = 'ontouchstart' in window,
169
-
170
- SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.navigator.pointerEnabled,
171
-
172
- SUPPORTS_POINTER = window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
173
-
174
- PLUGIN_NS = 'TouchSwipe';
175
-
176
-
177
-
178
- /**
179
- * The default configuration, and available options to configure touch swipe with.
180
- * You can set the default values by updating any of the properties prior to instantiation.
181
- * @name $.fn.swipe.defaults
182
- * @namespace
183
- * @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
184
- * @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe.
185
- * @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
186
- * @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch.
187
- * @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe.
188
- * @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers. If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release.
189
- * @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
190
- * @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
191
- * @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
192
- * @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
193
- * @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
194
- * @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
195
- * @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
196
- * @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
197
- * @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
198
- * @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
199
- * @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
200
- * @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not.
201
- * @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
202
- * @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
203
- * @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
204
- * @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger). If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically.
205
- * @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers.
206
- * @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}. <br/><br/>
207
- <code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
208
- <code>"none"</code> : the page will not scroll when user swipes. <br/>
209
- <code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
210
- <code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
211
- * @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non tocuh devices.
212
- * @property {string} [excludedElements="button, input, select, textarea, a, .noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes all form, input, select, button, anchor and .noSwipe elements.
213
- * @property {boolean} [preventDefaultEvents=true] by default default events are cancelled, so the page doesn't move. You can dissable this so both native events fire as well as your handlers.
214
 
215
- */
216
- var defaults = {
217
- fingers: 1,
218
- threshold: 75,
219
- cancelThreshold:null,
220
- pinchThreshold:20,
221
- maxTimeThreshold: null,
222
- fingerReleaseThreshold:250,
223
- longTapThreshold:500,
224
- doubleTapThreshold:200,
225
- swipe: null,
226
- swipeLeft: null,
227
- swipeRight: null,
228
- swipeUp: null,
229
- swipeDown: null,
230
- swipeStatus: null,
231
- pinchIn:null,
232
- pinchOut:null,
233
- pinchStatus:null,
234
- click:null, //Deprecated since 1.6.2
235
- tap:null,
236
- doubleTap:null,
237
- longTap:null,
238
- hold:null,
239
- triggerOnTouchEnd: true,
240
- triggerOnTouchLeave:false,
241
- allowPageScroll: "auto",
242
- fallbackToMouseEvents: true,
243
- excludedElements:"label, button, input, select, textarea, a, .noSwipe",
244
- preventDefaultEvents:true
245
- };
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
 
 
 
 
 
248
 
249
- /**
250
- * Applies TouchSwipe behaviour to one or more jQuery objects.
251
- * The TouchSwipe plugin can be instantiated via this method, or methods within
252
- * TouchSwipe can be executed via this method as per jQuery plugin architecture.
253
- * @see TouchSwipe
254
- * @class
255
- * @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
256
- * the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
257
- * If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the
258
- * configuration properties defined in the object. See TouchSwipe
259
- *
260
- */
261
- $.fn.swipe = function (method) {
262
- var $this = $(this),
263
- plugin = $this.data(PLUGIN_NS);
264
-
265
- //Check if we are already instantiated and trying to execute a method
266
- if (plugin && typeof method === 'string') {
267
- if (plugin[method]) {
268
- return plugin[method].apply(this, Array.prototype.slice.call(arguments, 1));
269
- } else {
270
- $.error('Method ' + method + ' does not exist on jQuery.swipe');
271
- }
272
- }
273
- //Else not instantiated and trying to pass init object (or nothing)
274
- else if (!plugin && (typeof method === 'object' || !method)) {
275
- return init.apply(this, arguments);
276
- }
277
 
278
- return $this;
279
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
 
281
- //Expose our defaults so a user could override the plugin defaults
282
- $.fn.swipe.defaults = defaults;
 
283
 
284
  /**
285
- * The phases that a touch event goes through. The <code>phase</code> is passed to the event handlers.
286
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
287
- * @namespace
288
- * @readonly
289
- * @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
290
- * @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
291
- * @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
292
- * @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
293
  */
294
- $.fn.swipe.phases = {
295
- PHASE_START: PHASE_START,
296
- PHASE_MOVE: PHASE_MOVE,
297
- PHASE_END: PHASE_END,
298
- PHASE_CANCEL: PHASE_CANCEL
 
299
  };
300
 
301
  /**
302
- * The direction constants that are passed to the event handlers.
303
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
304
- * @namespace
305
- * @readonly
306
- * @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
307
- * @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
308
- * @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
309
- * @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
310
- * @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
311
- * @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
312
  */
313
- $.fn.swipe.directions = {
314
- LEFT: LEFT,
315
- RIGHT: RIGHT,
316
- UP: UP,
317
- DOWN: DOWN,
318
- IN : IN,
319
- OUT: OUT
320
  };
321
 
322
  /**
323
- * The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
324
- * These properties are read only
325
- * @namespace
326
- * @readonly
327
- * @see $.fn.swipe.defaults#allowPageScroll
328
- * @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
329
- * @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
330
- * @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
331
- * @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
332
  */
333
- $.fn.swipe.pageScroll = {
334
- NONE: NONE,
335
- HORIZONTAL: HORIZONTAL,
336
- VERTICAL: VERTICAL,
337
- AUTO: AUTO
338
  };
339
 
340
- /**
341
- * Constants representing the number of fingers used in a swipe. These are used to set both the value of <code>fingers</code> in the
342
- * options object, as well as the value of the <code>fingers</code> event property.
343
- * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
344
- * @namespace
345
- * @readonly
346
- * @see $.fn.swipe.defaults#fingers
347
- * @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
348
- * @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>1</code>.
349
- * @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>1</code>.
350
- * @property {string} ALL Constant indicating any combination of finger are to be detected. Value is <code>"all"</code>.
351
- */
352
- $.fn.swipe.fingers = {
353
- ONE: 1,
354
- TWO: 2,
355
- THREE: 3,
356
- ALL: ALL_FINGERS
357
- };
358
 
359
  /**
360
- * Initialise the plugin for each DOM element matched
361
- * This creates a new instance of the main TouchSwipe class for each DOM element, and then
362
- * saves a reference to that instance in the elements data property.
363
- * @internal
 
 
 
 
 
 
 
 
 
364
  */
365
- function init(options) {
366
- //Prep and extend the options
367
- if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
368
- options.allowPageScroll = NONE;
369
- }
370
-
371
- //Check for deprecated options
372
- //Ensure that any old click handlers are assigned to the new tap, unless we have a tap
373
- if(options.click!==undefined && options.tap===undefined) {
374
- options.tap = options.click;
375
  }
 
 
 
 
 
376
 
377
- if (!options) {
378
- options = {};
379
- }
380
-
381
- //pass empty object so we dont modify the defaults
382
- options = $.extend({}, $.fn.swipe.defaults, options);
383
 
384
- //For each element instantiate the plugin
385
- return this.each(function () {
386
- var $this = $(this);
387
 
388
- //Check we havent already initialised the plugin
389
- var plugin = $this.data(PLUGIN_NS);
390
 
391
- if (!plugin) {
392
- plugin = new TouchSwipe(this, options);
393
- $this.data(PLUGIN_NS, plugin);
394
- }
395
- });
396
- }
397
 
 
 
 
398
  /**
399
- * Main TouchSwipe Plugin Class.
400
- * Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
401
- * @private
402
- * @name TouchSwipe
403
- * @param {DOMNode} element The HTML DOM object to apply to plugin to
404
- * @param {Object} options The options to configure the plugin with. @link {$.fn.swipe.defaults}
405
- * @see $.fh.swipe.defaults
406
- * @see $.fh.swipe
407
- * @class
408
  */
409
- function TouchSwipe(element, options) {
410
- var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
411
- START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
412
- MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
413
- END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
414
- LEAVE_EV = useTouchEvents ? null : 'mouseleave', //we manually detect leave on touch devices, so null event here
415
- CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
416
-
417
-
418
-
419
- //touch properties
420
- var distance = 0,
421
- direction = null,
422
- duration = 0,
423
- startTouchesDistance = 0,
424
- endTouchesDistance = 0,
425
- pinchZoom = 1,
426
- pinchDistance = 0,
427
- pinchDirection = 0,
428
- maximumsMap=null;
429
-
430
-
431
-
432
- //jQuery wrapped element for this instance
433
- var $element = $(element);
434
-
435
- //Current phase of th touch cycle
436
- var phase = "start";
437
-
438
- // the current number of fingers being used.
439
- var fingerCount = 0;
440
-
441
- //track mouse points / delta
442
- var fingerData=null;
443
-
444
- //track times
445
- var startTime = 0,
446
- endTime = 0,
447
- previousTouchEndTime=0,
448
- previousTouchFingerCount=0,
449
- doubleTapStartTime=0;
450
-
451
- //Timeouts
452
- var singleTapTimeout=null,
453
- holdTimeout=null;
454
-
455
- // Add gestures to all swipable areas if supported
456
- try {
457
- $element.bind(START_EV, touchStart);
458
- $element.bind(CANCEL_EV, touchCancel);
459
- }
460
- catch (e) {
461
- $.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
 
464
- //
465
- //Public methods
466
- //
467
-
468
- /**
469
- * re-enables the swipe plugin with the previous configuration
470
- * @function
471
- * @name $.fn.swipe#enable
472
- * @return {DOMNode} The Dom element that was registered with TouchSwipe
473
- * @example $("#element").swipe("enable");
474
- */
475
- this.enable = function () {
476
- $element.bind(START_EV, touchStart);
477
- $element.bind(CANCEL_EV, touchCancel);
478
- return $element;
479
- };
480
-
481
- /**
482
- * disables the swipe plugin
483
- * @function
484
- * @name $.fn.swipe#disable
485
- * @return {DOMNode} The Dom element that is now registered with TouchSwipe
486
- * @example $("#element").swipe("disable");
487
- */
488
- this.disable = function () {
489
- removeListeners();
490
- return $element;
491
- };
492
-
493
- /**
494
- * Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
495
- * @function
496
- * @name $.fn.swipe#destroy
497
- * @example $("#element").swipe("destroy");
498
- */
499
- this.destroy = function () {
500
- removeListeners();
501
- $element.data(PLUGIN_NS, null);
502
- $element = null;
503
- };
504
-
505
-
506
- /**
507
- * Allows run time updating of the swipe configuration options.
508
- * @function
509
- * @name $.fn.swipe#option
510
- * @param {String} property The option property to get or set
511
- * @param {Object} [value] The value to set the property to
512
- * @return {Object} If only a property name is passed, then that property value is returned.
513
- * @example $("#element").swipe("option", "threshold"); // return the threshold
514
- * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
515
- * @see $.fn.swipe.defaults
516
- *
517
- */
518
- this.option = function (property, value) {
519
- if(options[property]!==undefined) {
520
- if(value===undefined) {
521
- return options[property];
522
- } else {
523
- options[property] = value;
524
- }
525
- } else {
526
- $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
527
- }
528
-
529
- return null;
530
  }
531
-
532
- //
533
- // Private methods
534
- //
535
-
536
- //
537
- // EVENTS
538
- //
539
- /**
540
- * Event handler for a touch start event.
541
- * Stops the default click event from triggering and stores where we touched
542
- * @inner
543
- * @param {object} jqEvent The normalised jQuery event object.
544
- */
545
- function touchStart(jqEvent) {
546
- //If we already in a touch event (a finger already in use) then ignore subsequent ones..
547
- if( getTouchInProgress() )
548
- return;
549
-
550
- //Check if this element matches any in the excluded elements selectors, or its parent is excluded, if so, DON'T swipe
551
- if( $(jqEvent.target).closest( options.excludedElements, $element ).length>0 )
552
- return;
553
-
554
- //As we use Jquery bind for events, we need to target the original event object
555
- //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
556
- var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
557
-
558
- var ret,
559
- evt = SUPPORTS_TOUCH ? event.touches[0] : event;
560
-
561
- phase = PHASE_START;
562
-
563
- //If we support touches, get the finger count
564
- if (SUPPORTS_TOUCH) {
565
- // get the total number of fingers touching the screen
566
- fingerCount = event.touches.length;
567
  }
568
- //Else this is the desktop, so stop the browser from dragging content
569
- else {
570
- jqEvent.preventDefault(); //call this on jq event so we are cross browser
571
- }
572
-
573
- //clear vars..
574
- distance = 0;
575
- direction = null;
576
- pinchDirection=null;
577
- duration = 0;
578
- startTouchesDistance=0;
579
- endTouchesDistance=0;
580
- pinchZoom = 1;
581
- pinchDistance = 0;
582
- fingerData=createAllFingerData();
583
- maximumsMap=createMaximumsData();
584
- cancelMultiFingerRelease();
585
-
586
-
587
- // check the number of fingers is what we are looking for, or we are capturing pinches
588
- if (!SUPPORTS_TOUCH || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
589
- // get the coordinates of the touch
590
- createFingerData( 0, evt );
591
- startTime = getTimeStamp();
592
-
593
- if(fingerCount==2) {
594
- //Keep track of the initial pinch distance, so we can calculate the diff later
595
- //Store second finger data as start
596
- createFingerData( 1, event.touches[1] );
597
- startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
598
- }
599
-
600
- if (options.swipeStatus || options.pinchStatus) {
601
- ret = triggerHandler(event, phase);
602
- }
603
- }
604
- else {
605
- //A touch with more or less than the fingers we are looking for, so cancel
606
- ret = false;
607
- }
608
-
609
- //If we have a return value from the users handler, then return and cancel
610
- if (ret === false) {
611
- phase = PHASE_CANCEL;
612
- triggerHandler(event, phase);
613
- return ret;
614
- }
615
- else {
616
- if (options.hold) {
617
- holdTimeout = setTimeout($.proxy(function() {
618
- //Trigger the event
619
- $element.trigger('hold', [event.target]);
620
- //Fire the callback
621
- if(options.hold) {
622
- ret = options.hold.call($element, event, event.target);
623
- }
624
- }, this), options.longTapThreshold );
625
- }
626
-
627
- setTouchInProgress(true);
628
- }
629
-
630
- return null;
631
- };
632
-
633
-
634
-
635
- /**
636
- * Event handler for a touch move event.
637
- * If we change fingers during move, then cancel the event
638
- * @inner
639
- * @param {object} jqEvent The normalised jQuery event object.
640
- */
641
- function touchMove(jqEvent) {
642
 
643
- //As we use Jquery bind for events, we need to target the original event object
644
- //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
645
- var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
646
 
647
- //If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
648
- if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
649
- return;
650
 
651
- var ret,
652
- evt = SUPPORTS_TOUCH ? event.touches[0] : event;
653
 
654
 
655
- //Update the finger data
656
- var currentFinger = updateFingerData(evt);
657
- endTime = getTimeStamp();
 
 
 
 
658
 
659
- if (SUPPORTS_TOUCH) {
660
- fingerCount = event.touches.length;
661
- }
662
 
663
- if (options.hold)
664
- clearTimeout(holdTimeout);
 
665
 
666
- phase = PHASE_MOVE;
 
 
667
 
668
- //If we have 2 fingers get Touches distance as well
669
- if(fingerCount==2) {
670
 
671
- //Keep track of the initial pinch distance, so we can calculate the diff later
672
- //We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
673
- if(startTouchesDistance==0) {
674
- //Create second finger if this is the first time...
675
- createFingerData( 1, event.touches[1] );
676
 
677
- startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
678
- } else {
679
- //Else just update the second finger
680
- updateFingerData(event.touches[1]);
681
 
682
- endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
683
- pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
684
- }
685
 
 
686
 
687
- pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
688
- pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
689
- }
690
 
 
 
 
 
 
691
 
 
 
 
 
692
 
 
 
 
693
 
694
- if ( (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH || hasPinches() ) {
 
 
695
 
696
- direction = calculateDirection(currentFinger.start, currentFinger.end);
697
 
698
- //Check if we need to prevent default event (page scroll / pinch zoom) or not
699
- validateDefaultEvent(jqEvent, direction);
700
 
701
- //Distance and duration are all off the main finger
702
- distance = calculateDistance(currentFinger.start, currentFinger.end);
703
- duration = calculateDuration();
704
 
705
- //Cache the maximum distance we made in this direction
706
- setMaxDistance(direction, distance);
707
 
 
 
 
708
 
709
- if (options.swipeStatus || options.pinchStatus) {
710
- ret = triggerHandler(event, phase);
711
- }
712
 
 
 
713
 
714
- //If we trigger end events when threshold are met, or trigger events when touch leaves element
715
- if(!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
716
 
717
- var inBounds = true;
 
718
 
719
- //If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
720
- if(options.triggerOnTouchLeave) {
721
- var bounds = getbounds( this );
722
- inBounds = isInBounds( currentFinger.end, bounds );
723
- }
724
 
725
- //Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
726
- if(!options.triggerOnTouchEnd && inBounds) {
727
- phase = getNextPhase( PHASE_MOVE );
728
- }
729
- //We end if out of bounds here, so set current phase to END, and check if its modified
730
- else if(options.triggerOnTouchLeave && !inBounds ) {
731
- phase = getNextPhase( PHASE_END );
732
- }
733
 
734
- if(phase==PHASE_CANCEL || phase==PHASE_END) {
735
- triggerHandler(event, phase);
736
- }
737
- }
738
- }
739
- else {
740
- phase = PHASE_CANCEL;
741
- triggerHandler(event, phase);
742
- }
743
 
744
- if (ret === false) {
745
- phase = PHASE_CANCEL;
746
- triggerHandler(event, phase);
747
- }
748
  }
 
 
 
 
 
 
 
 
 
 
749
 
750
 
751
 
752
- /**
753
- * Event handler for a touch end event.
754
- * Calculate the direction and trigger events
755
- * @inner
756
- * @param {object} jqEvent The normalised jQuery event object.
757
- */
758
- function touchEnd(jqEvent) {
759
- //As we use Jquery bind for events, we need to target the original event object
760
- var event = jqEvent.originalEvent;
761
-
762
-
763
- //If we are still in a touch with another finger return
764
- //This allows us to wait a fraction and see if the other finger comes up, if it does within the threshold, then we treat it as a multi release, not a single release.
765
- if (SUPPORTS_TOUCH) {
766
- if(event.touches.length>0) {
767
- startMultiFingerRelease();
768
- return true;
769
- }
770
- }
771
-
772
- //If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
773
- //This is used to allow 2 fingers to release fractionally after each other, whilst maintainig the event as containg 2 fingers, not 1
774
- if(inMultiFingerRelease()) {
775
- fingerCount=previousTouchFingerCount;
776
- }
777
-
778
- //Set end of swipe
779
- endTime = getTimeStamp();
780
-
781
- //Get duration incase move was never fired
782
- duration = calculateDuration();
783
-
784
- //If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
785
- if(didSwipeBackToCancel() || !validateSwipeDistance()) {
786
- phase = PHASE_CANCEL;
787
- triggerHandler(event, phase);
788
- } else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd == false && phase === PHASE_MOVE)) {
789
- //call this on jq event so we are cross browser
790
- jqEvent.preventDefault();
791
- phase = PHASE_END;
792
- triggerHandler(event, phase);
793
- }
794
- //Special cases - A tap should always fire on touch end regardless,
795
- //So here we manually trigger the tap end handler by itself
796
- //We dont run trigger handler as it will re-trigger events that may have fired already
797
- else if (!options.triggerOnTouchEnd && hasTap()) {
798
- //Trigger the pinch events...
799
- phase = PHASE_END;
800
- triggerHandlerForGesture(event, phase, TAP);
801
- }
802
- else if (phase === PHASE_MOVE) {
803
- phase = PHASE_CANCEL;
804
- triggerHandler(event, phase);
805
- }
806
-
807
- setTouchInProgress(false);
808
 
809
- return null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
810
  }
811
-
812
-
813
-
814
- /**
815
- * Event handler for a touch cancel event.
816
- * Clears current vars
817
- * @inner
818
- */
819
- function touchCancel() {
820
- // reset the variables back to default values
821
- fingerCount = 0;
822
- endTime = 0;
823
- startTime = 0;
824
- startTouchesDistance=0;
825
- endTouchesDistance=0;
826
- pinchZoom=1;
827
-
828
- //If we were in progress of tracking a possible multi touch end, then re set it.
829
- cancelMultiFingerRelease();
830
-
831
- setTouchInProgress(false);
 
832
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
833
 
834
 
835
- /**
836
- * Event handler for a touch leave event.
837
- * This is only triggered on desktops, in touch we work this out manually
838
- * as the touchleave event is not supported in webkit
839
- * @inner
840
- */
841
- function touchLeave(jqEvent) {
842
- var event = jqEvent.originalEvent;
843
 
844
- //If we have the trigger on leave property set....
845
- if(options.triggerOnTouchLeave) {
846
- phase = getNextPhase( PHASE_END );
847
- triggerHandler(event, phase);
848
- }
849
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
850
 
851
- /**
852
- * Removes all listeners that were associated with the plugin
853
- * @inner
854
- */
855
- function removeListeners() {
856
- $element.unbind(START_EV, touchStart);
857
- $element.unbind(CANCEL_EV, touchCancel);
858
- $element.unbind(MOVE_EV, touchMove);
859
- $element.unbind(END_EV, touchEnd);
860
-
861
- //we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
862
- if(LEAVE_EV) {
863
- $element.unbind(LEAVE_EV, touchLeave);
864
- }
865
 
866
- setTouchInProgress(false);
867
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
868
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
869
 
870
- /**
871
- * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
872
- */
873
- function getNextPhase(currentPhase) {
874
 
875
- var nextPhase = currentPhase;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
876
 
877
- // Ensure we have valid swipe (under time and over distance and check if we are out of bound...)
878
- var validTime = validateSwipeTime();
879
- var validDistance = validateSwipeDistance();
880
- var didCancel = didSwipeBackToCancel();
881
 
882
- //If we have exceeded our time, then cancel
883
- if(!validTime || didCancel) {
884
- nextPhase = PHASE_CANCEL;
885
- }
886
- //Else if we are moving, and have reached distance then end
887
- else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) ) {
888
- nextPhase = PHASE_END;
889
- }
890
- //Else if we have ended by leaving and didn't reach distance, then cancel
891
- else if (!validDistance && currentPhase==PHASE_END && options.triggerOnTouchLeave) {
892
- nextPhase = PHASE_CANCEL;
893
- }
894
 
895
- return nextPhase;
896
- }
897
 
898
 
899
- /**
900
- * Trigger the relevant event handler
901
- * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
902
- * @param {object} event the original event object
903
- * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
904
- * @inner
905
- */
906
- function triggerHandler(event, phase) {
907
-
908
- var ret = undefined;
909
-
910
- //Swipes and pinches are not mutually exclusive - can happend at same time, so need to trigger 2 events potentially
911
- if( (didSwipe() || hasSwipes()) || (didPinch() || hasPinches()) ) {
912
- // SWIPE GESTURES
913
- if(didSwipe() || hasSwipes()) { //hasSwipes as status needs to fire even if swipe is invalid
914
- //Trigger the swipe events...
915
- ret = triggerHandlerForGesture(event, phase, SWIPE);
916
- }
917
-
918
- // PINCH GESTURES (if the above didn't cancel)
919
- if((didPinch() || hasPinches()) && ret!==false) {
920
- //Trigger the pinch events...
921
- ret = triggerHandlerForGesture(event, phase, PINCH);
922
- }
923
- } else {
924
-
925
- // CLICK / TAP (if the above didn't cancel)
926
- if(didDoubleTap() && ret!==false) {
927
- //Trigger the tap events...
928
- ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
929
- }
930
-
931
- // CLICK / TAP (if the above didn't cancel)
932
- else if(didLongTap() && ret!==false) {
933
- //Trigger the tap events...
934
- ret = triggerHandlerForGesture(event, phase, LONG_TAP);
935
- }
936
-
937
- // CLICK / TAP (if the above didn't cancel)
938
- else if(didTap() && ret!==false) {
939
- //Trigger the tap event..
940
- ret = triggerHandlerForGesture(event, phase, TAP);
941
- }
942
- }
943
 
 
 
 
 
944
 
 
 
 
 
945
 
946
- // If we are cancelling the gesture, then manually trigger the reset handler
947
- if (phase === PHASE_CANCEL) {
948
- touchCancel(event);
949
- }
 
950
 
951
- // If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
952
- if(phase === PHASE_END) {
953
- //If we support touch, then check that all fingers are off before we cancel
954
- if (SUPPORTS_TOUCH) {
955
- if(event.touches.length==0) {
956
- touchCancel(event);
957
- }
958
- }
959
- else {
960
- touchCancel(event);
961
- }
962
- }
963
 
964
- return ret;
965
- }
 
 
 
966
 
967
 
968
 
969
- /**
970
- * Trigger the relevant event handler
971
- * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
972
- * @param {object} event the original event object
973
- * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
974
- * @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
975
- * @return Boolean False, to indicate that the event should stop propagation, or void.
976
- * @inner
977
- */
978
- function triggerHandlerForGesture(event, phase, gesture) {
979
-
980
- var ret=undefined;
981
-
982
- //SWIPES....
983
- if(gesture==SWIPE) {
984
- //Trigger status every time..
985
-
986
- //Trigger the event...
987
- $element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData]);
988
-
989
- //Fire the callback
990
- if (options.swipeStatus) {
991
- ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData);
992
- //If the status cancels, then dont run the subsequent event handlers..
993
- if(ret===false) return false;
994
- }
995
-
996
-
997
-
998
-
999
- if (phase == PHASE_END && validateSwipe()) {
1000
- //Fire the catch all event
1001
- $element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData]);
1002
-
1003
- //Fire catch all callback
1004
- if (options.swipe) {
1005
- ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData);
1006
- //If the status cancels, then dont run the subsequent event handlers..
1007
- if(ret===false) return false;
1008
- }
1009
-
1010
- //trigger direction specific event handlers
1011
- switch (direction) {
1012
- case LEFT:
1013
- //Trigger the event
1014
- $element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData]);
1015
-
1016
- //Fire the callback
1017
- if (options.swipeLeft) {
1018
- ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData);
1019
- }
1020
- break;
1021
-
1022
- case RIGHT:
1023
- //Trigger the event
1024
- $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData]);
1025
-
1026
- //Fire the callback
1027
- if (options.swipeRight) {
1028
- ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData);
1029
- }
1030
- break;
1031
-
1032
- case UP:
1033
- //Trigger the event
1034
- $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData]);
1035
-
1036
- //Fire the callback
1037
- if (options.swipeUp) {
1038
- ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData);
1039
- }
1040
- break;
1041
-
1042
- case DOWN:
1043
- //Trigger the event
1044
- $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData]);
1045
-
1046
- //Fire the callback
1047
- if (options.swipeDown) {
1048
- ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData);
1049
- }
1050
- break;
1051
- }
1052
- }
1053
- }
1054
 
 
 
1055
 
1056
- //PINCHES....
1057
- if(gesture==PINCH) {
1058
- //Trigger the event
1059
- $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1060
-
1061
- //Fire the callback
1062
- if (options.pinchStatus) {
1063
- ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1064
- //If the status cancels, then dont run the subsequent event handlers..
1065
- if(ret===false) return false;
1066
- }
1067
-
1068
- if(phase==PHASE_END && validatePinch()) {
1069
-
1070
- switch (pinchDirection) {
1071
- case IN:
1072
- //Trigger the event
1073
- $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1074
-
1075
- //Fire the callback
1076
- if (options.pinchIn) {
1077
- ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1078
- }
1079
- break;
1080
-
1081
- case OUT:
1082
- //Trigger the event
1083
- $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1084
-
1085
- //Fire the callback
1086
- if (options.pinchOut) {
1087
- ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1088
- }
1089
- break;
1090
- }
1091
- }
1092
- }
1093
 
1094
 
1095
 
 
 
 
 
 
 
 
 
 
 
 
1096
 
 
 
1097
 
1098
- if(gesture==TAP) {
1099
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
1100
 
1101
 
1102
- //Cancel any existing double tap
1103
- clearTimeout(singleTapTimeout);
1104
- //Cancel hold timeout
1105
- clearTimeout(holdTimeout);
 
 
 
 
 
 
1106
 
1107
- //If we are also looking for doubelTaps, wait incase this is one...
1108
- if(hasDoubleTap() && !inDoubleTap()) {
1109
- //Cache the time of this tap
1110
- doubleTapStartTime = getTimeStamp();
1111
 
1112
- //Now wait for the double tap timeout, and trigger this single tap
1113
- //if its not cancelled by a double tap
1114
- singleTapTimeout = setTimeout($.proxy(function() {
1115
- doubleTapStartTime=null;
1116
- //Trigger the event
1117
- $element.trigger('tap', [event.target]);
1118
 
 
 
 
 
 
1119
 
1120
- //Fire the callback
1121
- if(options.tap) {
1122
- ret = options.tap.call($element, event, event.target);
1123
- }
1124
- }, this), options.doubleTapThreshold );
1125
 
1126
- } else {
1127
- doubleTapStartTime=null;
 
1128
 
1129
- //Trigger the event
1130
- $element.trigger('tap', [event.target]);
1131
 
 
 
 
 
 
1132
 
1133
- //Fire the callback
1134
- if(options.tap) {
1135
- ret = options.tap.call($element, event, event.target);
1136
- }
1137
- }
1138
- }
1139
- }
1140
 
1141
- else if (gesture==DOUBLE_TAP) {
1142
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
1143
- //Cancel any pending singletap
1144
- clearTimeout(singleTapTimeout);
1145
- doubleTapStartTime=null;
1146
 
1147
- //Trigger the event
1148
- $element.trigger('doubletap', [event.target]);
1149
 
1150
- //Fire the callback
1151
- if(options.doubleTap) {
1152
- ret = options.doubleTap.call($element, event, event.target);
1153
- }
1154
- }
1155
- }
1156
 
1157
- else if (gesture==LONG_TAP) {
1158
- if(phase === PHASE_CANCEL || phase === PHASE_END) {
1159
- //Cancel any pending singletap (shouldnt be one)
1160
- clearTimeout(singleTapTimeout);
1161
- doubleTapStartTime=null;
1162
 
1163
- //Trigger the event
1164
- $element.trigger('longtap', [event.target]);
 
 
1165
 
1166
- //Fire the callback
1167
- if(options.longTap) {
1168
- ret = options.longTap.call($element, event, event.target);
1169
- }
1170
- }
1171
- }
1172
 
1173
- return ret;
 
 
 
 
1174
  }
 
1175
 
1176
 
 
 
 
1177
 
1178
-
1179
- //
1180
- // GESTURE VALIDATION
1181
- //
1182
-
1183
- /**
1184
- * Checks the user has swipe far enough
1185
- * @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
1186
- * If no threshold was set, then we return true.
1187
- * @inner
1188
- */
1189
- function validateSwipeDistance() {
1190
- var valid = true;
1191
- //If we made it past the min swipe distance..
1192
- if (options.threshold !== null) {
1193
- valid = distance >= options.threshold;
1194
- }
1195
-
1196
- return valid;
1197
  }
1198
 
1199
- /**
1200
- * Checks the user has swiped back to cancel.
1201
- * @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
1202
- * If no cancelThreshold was set, then we return true.
1203
- * @inner
1204
- */
1205
- function didSwipeBackToCancel() {
1206
- var cancelled = false;
1207
- if(options.cancelThreshold !== null && direction !==null) {
1208
- cancelled = (getMaxDistance( direction ) - distance) >= options.cancelThreshold;
1209
- }
1210
 
1211
- return cancelled;
1212
- }
 
1213
 
1214
- /**
1215
- * Checks the user has pinched far enough
1216
- * @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
1217
- * If no threshold was set, then we return true.
1218
- * @inner
1219
- */
1220
- function validatePinchDistance() {
1221
- if (options.pinchThreshold !== null) {
1222
- return pinchDistance >= options.pinchThreshold;
1223
- }
1224
- return true;
1225
- }
1226
 
1227
- /**
1228
- * Checks that the time taken to swipe meets the minimum / maximum requirements
1229
- * @return Boolean
1230
- * @inner
1231
- */
1232
- function validateSwipeTime() {
1233
- var result;
1234
- //If no time set, then return true
1235
-
1236
- if (options.maxTimeThreshold) {
1237
- if (duration >= options.maxTimeThreshold) {
1238
- result = false;
1239
- } else {
1240
- result = true;
1241
- }
1242
- }
1243
- else {
1244
- result = true;
1245
- }
1246
 
1247
- return result;
 
 
 
 
1248
  }
1249
-
1250
-
1251
-
1252
- /**
1253
- * Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
1254
- * This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
1255
- * @param {object} jqEvent The normalised jQuery representation of the event object.
1256
- * @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
1257
- * @see $.fn.swipe.directions
1258
- * @inner
1259
- */
1260
- function validateDefaultEvent(jqEvent, direction) {
1261
-
1262
-
1263
- if( options.preventDefaultEvents === false ) {
1264
- return;
1265
- }
1266
-
1267
- if (options.allowPageScroll === NONE) {
1268
- jqEvent.preventDefault();
1269
- } else {
1270
- var auto = options.allowPageScroll === AUTO;
1271
-
1272
- switch (direction) {
1273
- case LEFT:
1274
- if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1275
- jqEvent.preventDefault();
1276
- }
1277
- break;
1278
-
1279
- case RIGHT:
1280
- if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1281
- jqEvent.preventDefault();
1282
- }
1283
- break;
1284
-
1285
- case UP:
1286
- if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1287
- jqEvent.preventDefault();
1288
- }
1289
- break;
1290
-
1291
- case DOWN:
1292
- if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1293
- jqEvent.preventDefault();
1294
- }
1295
- break;
1296
- }
1297
  }
1298
-
1299
  }
1300
-
1301
-
1302
- // PINCHES
1303
- /**
1304
- * Returns true of the current pinch meets the thresholds
1305
- * @return Boolean
1306
- * @inner
1307
- */
1308
- function validatePinch() {
1309
- var hasCorrectFingerCount = validateFingers();
1310
- var hasEndPoint = validateEndPoint();
1311
- var hasCorrectDistance = validatePinchDistance();
1312
- return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
1313
-
1314
  }
1315
-
1316
- /**
1317
- * Returns true if any Pinch events have been registered
1318
- * @return Boolean
1319
- * @inner
1320
- */
1321
- function hasPinches() {
1322
- //Enure we dont return 0 or null for false values
1323
- return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
1324
- }
1325
-
1326
- /**
1327
- * Returns true if we are detecting pinches, and have one
1328
- * @return Boolean
1329
- * @inner
1330
- */
1331
- function didPinch() {
1332
- //Enure we dont return 0 or null for false values
1333
- return !!(validatePinch() && hasPinches());
1334
  }
 
1335
 
 
 
1336
 
1337
 
 
 
 
1338
 
1339
- // SWIPES
1340
- /**
1341
- * Returns true if the current swipe meets the thresholds
1342
- * @return Boolean
1343
- * @inner
1344
- */
1345
- function validateSwipe() {
1346
- //Check validity of swipe
1347
- var hasValidTime = validateSwipeTime();
1348
- var hasValidDistance = validateSwipeDistance();
1349
- var hasCorrectFingerCount = validateFingers();
1350
- var hasEndPoint = validateEndPoint();
1351
- var didCancel = didSwipeBackToCancel();
1352
-
1353
- // if the user swiped more than the minimum length, perform the appropriate action
1354
- // hasValidDistance is null when no distance is set
1355
- var valid = !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
1356
-
1357
- return valid;
1358
- }
1359
 
1360
- /**
1361
- * Returns true if any Swipe events have been registered
1362
- * @return Boolean
1363
- * @inner
1364
- */
1365
- function hasSwipes() {
1366
- //Enure we dont return 0 or null for false values
1367
- return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
1368
- }
 
 
1369
 
 
 
1370
 
1371
- /**
1372
- * Returns true if we are detecting swipes and have one
1373
- * @return Boolean
1374
- * @inner
1375
- */
1376
- function didSwipe() {
1377
- //Enure we dont return 0 or null for false values
1378
- return !!(validateSwipe() && hasSwipes());
1379
- }
 
 
 
1380
 
1381
- /**
1382
- * Returns true if we have matched the number of fingers we are looking for
1383
- * @return Boolean
1384
- * @inner
1385
- */
1386
- function validateFingers() {
1387
- //The number of fingers we want were matched, or on desktop we ignore
1388
- return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
 
 
 
 
 
1389
  }
 
 
 
1390
 
1391
- /**
1392
- * Returns true if we have an end point for the swipe
1393
- * @return Boolean
1394
- * @inner
1395
- */
1396
- function validateEndPoint() {
1397
- //We have an end value for the finger
1398
- return fingerData[0].end.x !== 0;
1399
- }
1400
 
1401
- // TAP / CLICK
1402
- /**
1403
- * Returns true if a click / tap events have been registered
1404
- * @return Boolean
1405
- * @inner
1406
- */
1407
- function hasTap() {
1408
- //Enure we dont return 0 or null for false values
1409
- return !!(options.tap) ;
1410
- }
1411
 
1412
- /**
1413
- * Returns true if a double tap events have been registered
1414
- * @return Boolean
1415
- * @inner
1416
- */
1417
- function hasDoubleTap() {
1418
- //Enure we dont return 0 or null for false values
1419
- return !!(options.doubleTap) ;
1420
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1421
 
1422
- /**
1423
- * Returns true if any long tap events have been registered
1424
- * @return Boolean
1425
- * @inner
1426
- */
1427
- function hasLongTap() {
1428
- //Enure we dont return 0 or null for false values
1429
- return !!(options.longTap) ;
1430
- }
1431
 
1432
- /**
1433
- * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1434
- * @return Boolean
1435
- * @inner
1436
- */
1437
- function validateDoubleTap() {
1438
- if(doubleTapStartTime==null){
1439
- return false;
1440
  }
1441
- var now = getTimeStamp();
1442
- return (hasDoubleTap() && ((now-doubleTapStartTime) <= options.doubleTapThreshold));
1443
- }
1444
 
1445
- /**
1446
- * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1447
- * @return Boolean
1448
- * @inner
1449
- */
1450
- function inDoubleTap() {
1451
- return validateDoubleTap();
1452
- }
1453
 
 
1454
 
1455
- /**
1456
- * Returns true if we have a valid tap
1457
- * @return Boolean
1458
- * @inner
1459
- */
1460
- function validateTap() {
1461
- return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
1462
  }
 
 
1463
 
1464
- /**
1465
- * Returns true if we have a valid long tap
1466
- * @return Boolean
1467
- * @inner
1468
- */
1469
- function validateLongTap() {
1470
- //slight threshold on moving finger
1471
- return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD));
1472
- }
1473
 
1474
- /**
1475
- * Returns true if we are detecting taps and have one
1476
- * @return Boolean
1477
- * @inner
1478
- */
1479
- function didTap() {
1480
- //Enure we dont return 0 or null for false values
1481
- return !!(validateTap() && hasTap());
1482
- }
 
 
1483
 
 
1484
 
1485
- /**
1486
- * Returns true if we are detecting double taps and have one
1487
- * @return Boolean
1488
- * @inner
1489
- */
1490
- function didDoubleTap() {
1491
- //Enure we dont return 0 or null for false values
1492
- return !!(validateDoubleTap() && hasDoubleTap());
1493
- }
1494
 
1495
- /**
1496
- * Returns true if we are detecting long taps and have one
1497
- * @return Boolean
1498
- * @inner
1499
- */
1500
- function didLongTap() {
1501
- //Enure we dont return 0 or null for false values
1502
- return !!(validateLongTap() && hasLongTap());
1503
- }
1504
 
1505
 
1506
 
1507
 
1508
- // MULTI FINGER TOUCH
1509
- /**
1510
- * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
1511
- * @inner
1512
- */
1513
- function startMultiFingerRelease() {
1514
- previousTouchEndTime = getTimeStamp();
1515
- previousTouchFingerCount = event.touches.length+1;
1516
- }
 
 
 
 
 
 
 
 
 
 
 
1517
 
1518
- /**
1519
- * Cancels the tracking of time between 2 finger releases, and resets counters
1520
- * @inner
1521
- */
1522
- function cancelMultiFingerRelease() {
1523
- previousTouchEndTime = 0;
1524
- previousTouchFingerCount = 0;
1525
- }
 
1526
 
1527
- /**
1528
- * Checks if we are in the threshold between 2 fingers being released
1529
- * @return Boolean
1530
- * @inner
1531
- */
1532
- function inMultiFingerRelease() {
1533
 
1534
- var withinThreshold = false;
 
 
 
 
 
 
 
 
1535
 
1536
- if(previousTouchEndTime) {
1537
- var diff = getTimeStamp() - previousTouchEndTime
1538
- if( diff<=options.fingerReleaseThreshold ) {
1539
- withinThreshold = true;
1540
- }
1541
- }
 
 
 
1542
 
1543
- return withinThreshold;
1544
- }
 
 
 
 
 
 
 
1545
 
 
 
 
 
 
 
 
 
 
 
1546
 
1547
- /**
1548
- * gets a data flag to indicate that a touch is in progress
1549
- * @return Boolean
1550
- * @inner
1551
- */
1552
- function getTouchInProgress() {
1553
- //strict equality to ensure only true and false are returned
1554
- return !!($element.data(PLUGIN_NS+'_intouch') === true);
1555
- }
1556
 
1557
- /**
1558
- * Sets a data flag to indicate that a touch is in progress
1559
- * @param {boolean} val The value to set the property to
1560
- * @inner
1561
- */
1562
- function setTouchInProgress(val) {
1563
-
1564
- //Add or remove event listeners depending on touch status
1565
- if(val===true) {
1566
- $element.bind(MOVE_EV, touchMove);
1567
- $element.bind(END_EV, touchEnd);
1568
-
1569
- //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1570
- if(LEAVE_EV) {
1571
- $element.bind(LEAVE_EV, touchLeave);
1572
- }
1573
- } else {
1574
- $element.unbind(MOVE_EV, touchMove, false);
1575
- $element.unbind(END_EV, touchEnd, false);
1576
-
1577
- //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1578
- if(LEAVE_EV) {
1579
- $element.unbind(LEAVE_EV, touchLeave, false);
1580
- }
1581
- }
1582
 
 
 
 
 
 
 
 
 
 
 
 
 
1583
 
1584
- //strict equality to ensure only true and false can update the value
1585
- $element.data(PLUGIN_NS+'_intouch', val === true);
1586
- }
 
 
 
 
 
1587
 
1588
 
1589
- /**
1590
- * Creates the finger data for the touch/finger in the event object.
1591
- * @param {int} index The index in the array to store the finger data (usually the order the fingers were pressed)
1592
- * @param {object} evt The event object containing finger data
1593
- * @return finger data object
1594
- * @inner
1595
- */
1596
- function createFingerData( index, evt ) {
1597
- var id = evt.identifier!==undefined ? evt.identifier : 0;
1598
 
1599
- fingerData[index].identifier = id;
1600
- fingerData[index].start.x = fingerData[index].end.x = evt.pageX||evt.clientX;
1601
- fingerData[index].start.y = fingerData[index].end.y = evt.pageY||evt.clientY;
 
 
 
 
 
 
1602
 
1603
- return fingerData[index];
1604
- }
 
 
 
 
 
 
 
1605
 
1606
- /**
1607
- * Updates the finger data for a particular event object
1608
- * @param {object} evt The event object containing the touch/finger data to upadte
1609
- * @return a finger data object.
1610
- * @inner
1611
- */
1612
- function updateFingerData(evt) {
1613
 
1614
- var id = evt.identifier!==undefined ? evt.identifier : 0;
1615
- var f = getFingerData( id );
 
 
 
 
 
 
 
1616
 
1617
- f.end.x = evt.pageX||evt.clientX;
1618
- f.end.y = evt.pageY||evt.clientY;
 
 
 
 
 
 
 
1619
 
1620
- return f;
1621
- }
1622
 
1623
- /**
1624
- * Returns a finger data object by its event ID.
1625
- * Each touch event has an identifier property, which is used
1626
- * to track repeat touches
1627
- * @param {int} id The unique id of the finger in the sequence of touch events.
1628
- * @return a finger data object.
1629
- * @inner
1630
- */
1631
- function getFingerData( id ) {
1632
- for(var i=0; i<fingerData.length; i++) {
1633
- if(fingerData[i].identifier == id) {
1634
- return fingerData[i];
1635
- }
1636
- }
1637
- }
1638
 
1639
- /**
1640
- * Creats all the finger onjects and returns an array of finger data
1641
- * @return Array of finger objects
1642
- * @inner
1643
- */
1644
- function createAllFingerData() {
1645
- var fingerData=[];
1646
- for (var i=0; i<=5; i++) {
1647
- fingerData.push({
1648
- start:{ x: 0, y: 0 },
1649
- end:{ x: 0, y: 0 },
1650
- identifier:0
1651
- });
1652
- }
1653
 
1654
- return fingerData;
1655
- }
 
 
 
 
 
 
 
1656
 
1657
- /**
1658
- * Sets the maximum distance swiped in the given direction.
1659
- * If the new value is lower than the current value, the max value is not changed.
1660
- * @param {string} direction The direction of the swipe
1661
- * @param {int} distance The distance of the swipe
1662
- * @inner
1663
- */
1664
- function setMaxDistance(direction, distance) {
1665
- distance = Math.max(distance, getMaxDistance(direction) );
1666
- maximumsMap[direction].distance = distance;
1667
- }
1668
 
1669
- /**
1670
- * gets the maximum distance swiped in the given direction.
1671
- * @param {string} direction The direction of the swipe
1672
- * @return int The distance of the swipe
1673
- * @inner
1674
- */
1675
- function getMaxDistance(direction) {
1676
- if (maximumsMap[direction]) return maximumsMap[direction].distance;
1677
- return undefined;
1678
- }
1679
 
1680
- /**
1681
- * Creats a map of directions to maximum swiped values.
1682
- * @return Object A dictionary of maximum values, indexed by direction.
1683
- * @inner
1684
- */
1685
- function createMaximumsData() {
1686
- var maxData={};
1687
- maxData[LEFT]=createMaximumVO(LEFT);
1688
- maxData[RIGHT]=createMaximumVO(RIGHT);
1689
- maxData[UP]=createMaximumVO(UP);
1690
- maxData[DOWN]=createMaximumVO(DOWN);
1691
-
1692
- return maxData;
1693
- }
1694
 
1695
- /**
1696
- * Creates a map maximum swiped values for a given swipe direction
1697
- * @param {string} The direction that these values will be associated with
1698
- * @return Object Maximum values
1699
- * @inner
1700
- */
1701
- function createMaximumVO(dir) {
1702
- return {
1703
- direction:dir,
1704
- distance:0
1705
- }
1706
  }
 
1707
 
 
 
1708
 
1709
- //
1710
- // MATHS / UTILS
1711
- //
1712
 
1713
- /**
1714
- * Calculate the duration of the swipe
1715
- * @return int
1716
- * @inner
1717
- */
1718
- function calculateDuration() {
1719
- return endTime - startTime;
1720
- }
 
1721
 
1722
- /**
1723
- * Calculate the distance between 2 touches (pinch)
1724
- * @param {point} startPoint A point object containing x and y co-ordinates
1725
- * @param {point} endPoint A point object containing x and y co-ordinates
1726
- * @return int;
1727
- * @inner
1728
- */
1729
- function calculateTouchesDistance(startPoint, endPoint) {
1730
- var diffX = Math.abs(startPoint.x - endPoint.x);
1731
- var diffY = Math.abs(startPoint.y - endPoint.y);
1732
-
1733
- return Math.round(Math.sqrt(diffX*diffX+diffY*diffY));
1734
- }
1735
 
1736
- /**
1737
- * Calculate the zoom factor between the start and end distances
1738
- * @param {int} startDistance Distance (between 2 fingers) the user started pinching at
1739
- * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
1740
- * @return float The zoom value from 0 to 1.
1741
- * @inner
1742
- */
1743
- function calculatePinchZoom(startDistance, endDistance) {
1744
- var percent = (endDistance/startDistance) * 1;
1745
- return percent.toFixed(2);
1746
- }
1747
 
 
 
 
 
1748
 
1749
- /**
1750
- * Returns the pinch direction, either IN or OUT for the given points
1751
- * @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
1752
- * @see $.fn.swipe.directions
1753
- * @inner
1754
- */
1755
- function calculatePinchDirection() {
1756
- if(pinchZoom<1) {
1757
- return OUT;
1758
- }
1759
- else {
1760
- return IN;
1761
- }
1762
  }
 
1763
 
 
 
1764
 
1765
- /**
1766
- * Calculate the length / distance of the swipe
1767
- * @param {point} startPoint A point object containing x and y co-ordinates
1768
- * @param {point} endPoint A point object containing x and y co-ordinates
1769
- * @return int
1770
- * @inner
1771
- */
1772
- function calculateDistance(startPoint, endPoint) {
1773
- return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
1774
  }
 
1775
 
1776
- /**
1777
- * Calculate the angle of the swipe
1778
- * @param {point} startPoint A point object containing x and y co-ordinates
1779
- * @param {point} endPoint A point object containing x and y co-ordinates
1780
- * @return int
1781
- * @inner
1782
- */
1783
- function calculateAngle(startPoint, endPoint) {
1784
- var x = startPoint.x - endPoint.x;
1785
- var y = endPoint.y - startPoint.y;
1786
- var r = Math.atan2(y, x); //radians
1787
- var angle = Math.round(r * 180 / Math.PI); //degrees
1788
-
1789
- //ensure value is positive
1790
- if (angle < 0) {
1791
- angle = 360 - Math.abs(angle);
1792
- }
1793
-
1794
- return angle;
1795
- }
1796
 
1797
- /**
1798
- * Calculate the direction of the swipe
1799
- * This will also call calculateAngle to get the latest angle of swipe
1800
- * @param {point} startPoint A point object containing x and y co-ordinates
1801
- * @param {point} endPoint A point object containing x and y co-ordinates
1802
- * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
1803
- * @see $.fn.swipe.directions
1804
- * @inner
1805
- */
1806
- function calculateDirection(startPoint, endPoint ) {
1807
- var angle = calculateAngle(startPoint, endPoint);
1808
-
1809
- if ((angle <= 45) && (angle >= 0)) {
1810
- return LEFT;
1811
- } else if ((angle <= 360) && (angle >= 315)) {
1812
- return LEFT;
1813
- } else if ((angle >= 135) && (angle <= 225)) {
1814
- return RIGHT;
1815
- } else if ((angle > 45) && (angle < 135)) {
1816
- return DOWN;
1817
- } else {
1818
- return UP;
1819
- }
1820
- }
1821
 
1822
 
1823
- /**
1824
- * Returns a MS time stamp of the current time
1825
- * @return int
1826
- * @inner
1827
- */
1828
- function getTimeStamp() {
1829
- var now = new Date();
1830
- return now.getTime();
 
 
 
 
 
 
 
 
 
 
 
 
1831
  }
 
 
 
 
 
 
1832
 
 
 
 
 
 
 
 
 
 
1833
 
 
 
 
1834
 
1835
- /**
1836
- * Returns a bounds object with left, right, top and bottom properties for the element specified.
1837
- * @param {DomNode} The DOM node to get the bounds for.
1838
- */
1839
- function getbounds( el ) {
1840
- el = $(el);
1841
- var offset = el.offset();
1842
-
1843
- var bounds = {
1844
- left:offset.left,
1845
- right:offset.left+el.outerWidth(),
1846
- top:offset.top,
1847
- bottom:offset.top+el.outerHeight()
1848
- }
1849
-
1850
- return bounds;
1851
- }
1852
-
1853
-
1854
- /**
1855
- * Checks if the point object is in the bounds object.
1856
- * @param {object} point A point object.
1857
- * @param {int} point.x The x value of the point.
1858
- * @param {int} point.y The x value of the point.
1859
- * @param {object} bounds The bounds object to test
1860
- * @param {int} bounds.left The leftmost value
1861
- * @param {int} bounds.right The righttmost value
1862
- * @param {int} bounds.top The topmost value
1863
- * @param {int} bounds.bottom The bottommost value
1864
- */
1865
- function isInBounds(point, bounds) {
1866
- return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
1867
- };
1868
 
 
 
1869
 
 
1870
  }
1871
 
1872
-
1873
-
1874
-
1875
  /**
1876
- * A catch all handler that is triggered for all swipe directions.
1877
- * @name $.fn.swipe#swipe
1878
- * @event
1879
- * @default null
1880
- * @param {EventObject} event The original event object
1881
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1882
- * @param {int} distance The distance the user swiped
1883
- * @param {int} duration The duration of the swipe in milliseconds
1884
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1885
- * @param {object} fingerData The coordinates of fingers in event
1886
  */
 
 
 
1887
 
1888
 
 
 
 
 
 
 
 
 
 
 
 
 
1889
 
 
 
 
 
 
 
 
 
 
 
1890
 
1891
  /**
1892
- * A handler that is triggered for "left" swipes.
1893
- * @name $.fn.swipe#swipeLeft
1894
- * @event
1895
- * @default null
1896
- * @param {EventObject} event The original event object
1897
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1898
- * @param {int} distance The distance the user swiped
1899
- * @param {int} duration The duration of the swipe in milliseconds
1900
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1901
- * @param {object} fingerData The coordinates of fingers in event
1902
  */
 
 
 
 
 
 
 
 
 
1903
 
1904
  /**
1905
- * A handler that is triggered for "right" swipes.
1906
- * @name $.fn.swipe#swipeRight
1907
- * @event
1908
- * @default null
1909
- * @param {EventObject} event The original event object
1910
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1911
- * @param {int} distance The distance the user swiped
1912
- * @param {int} duration The duration of the swipe in milliseconds
1913
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1914
- * @param {object} fingerData The coordinates of fingers in event
1915
  */
 
 
 
 
 
 
 
 
 
 
 
1916
 
1917
  /**
1918
- * A handler that is triggered for "up" swipes.
1919
- * @name $.fn.swipe#swipeUp
1920
- * @event
1921
- * @default null
1922
- * @param {EventObject} event The original event object
1923
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1924
- * @param {int} distance The distance the user swiped
1925
- * @param {int} duration The duration of the swipe in milliseconds
1926
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1927
- * @param {object} fingerData The coordinates of fingers in event
1928
  */
 
 
 
1929
 
1930
  /**
1931
- * A handler that is triggered for "down" swipes.
1932
- * @name $.fn.swipe#swipeDown
1933
- * @event
1934
- * @default null
1935
- * @param {EventObject} event The original event object
1936
- * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1937
- * @param {int} distance The distance the user swiped
1938
- * @param {int} duration The duration of the swipe in milliseconds
1939
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1940
- * @param {object} fingerData The coordinates of fingers in event
1941
  */
 
 
 
 
 
 
1942
 
1943
  /**
1944
- * A handler triggered for every phase of the swipe. This handler is constantly fired for the duration of the pinch.
1945
- * This is triggered regardless of swipe thresholds.
1946
- * @name $.fn.swipe#swipeStatus
1947
- * @event
1948
- * @default null
1949
- * @param {EventObject} event The original event object
1950
- * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
1951
- * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
1952
- * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
1953
- * @param {int} duration The duration of the swipe in milliseconds
1954
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1955
- * @param {object} fingerData The coordinates of fingers in event
1956
  */
 
 
 
 
 
1957
 
1958
  /**
1959
- * A handler triggered for pinch in events.
1960
- * @name $.fn.swipe#pinchIn
1961
- * @event
1962
- * @default null
1963
- * @param {EventObject} event The original event object
1964
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1965
- * @param {int} distance The distance the user pinched
1966
- * @param {int} duration The duration of the swipe in milliseconds
1967
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1968
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1969
- * @param {object} fingerData The coordinates of fingers in event
1970
  */
 
 
 
 
 
 
 
 
1971
 
1972
  /**
1973
- * A handler triggered for pinch out events.
1974
- * @name $.fn.swipe#pinchOut
1975
- * @event
1976
- * @default null
1977
- * @param {EventObject} event The original event object
1978
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1979
- * @param {int} distance The distance the user pinched
1980
- * @param {int} duration The duration of the swipe in milliseconds
1981
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1982
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1983
- * @param {object} fingerData The coordinates of fingers in event
1984
  */
 
 
 
1985
 
1986
  /**
1987
- * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
1988
- * @name $.fn.swipe#pinchStatus
1989
- * @event
1990
- * @default null
1991
- * @param {EventObject} event The original event object
1992
- * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
1993
- * @param {int} distance The distance the user pinched
1994
- * @param {int} duration The duration of the swipe in milliseconds
1995
- * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1996
- * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
1997
- * @param {object} fingerData The coordinates of fingers in event
1998
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
1999
 
2000
  /**
2001
- * A click handler triggered when a user simply clicks, rather than swipes on an element.
2002
- * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
2003
- * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
2004
- * Use the <code>tap</code> event instead.
2005
- * @name $.fn.swipe#click
2006
- * @event
2007
- * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead
2008
- * @default null
2009
- * @param {EventObject} event The original event object
2010
- * @param {DomObject} target The element clicked on.
2011
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2012
 
2013
  /**
2014
- * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
2015
- * @name $.fn.swipe#tap
2016
- * @event
2017
- * @default null
2018
- * @param {EventObject} event The original event object
2019
- * @param {DomObject} target The element clicked on.
2020
  */
 
 
 
 
 
 
2021
 
2022
  /**
2023
- * A double tap handler triggered when a user double clicks or taps on an element.
2024
- * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property.
2025
- * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
2026
- * as the script needs to check if its a double tap.
2027
- * @name $.fn.swipe#doubleTap
2028
- * @see $.fn.swipe.defaults#doubleTapThreshold
2029
- * @event
2030
- * @default null
2031
- * @param {EventObject} event The original event object
2032
- * @param {DomObject} target The element clicked on.
2033
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2034
 
2035
  /**
2036
- * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
2037
- * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2038
- * @name $.fn.swipe#longTap
2039
- * @see $.fn.swipe.defaults#longTapThreshold
2040
- * @event
2041
- * @default null
2042
- * @param {EventObject} event The original event object
2043
- * @param {DomObject} target The element clicked on.
 
2044
  */
 
 
 
2045
 
2046
  /**
2047
- * A hold tap handler triggered as soon as the longTapThreshold is reached
2048
- * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2049
- * @name $.fn.swipe#hold
2050
- * @see $.fn.swipe.defaults#longTapThreshold
2051
- * @event
2052
- * @default null
2053
- * @param {EventObject} event The original event object
2054
- * @param {DomObject} target The element clicked on.
2055
  */
 
 
 
 
2056
 
2057
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
  * @fileOverview TouchSwipe - jQuery Plugin
3
+ * @version 1.6.18
4
  *
5
  * @author Matt Bryson http://www.github.com/mattbryson
6
  * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
7
  * @see http://labs.rampinteractive.co.uk/touchSwipe/
8
  * @see http://plugins.jquery.com/project/touchSwipe
9
+ * @license
10
  * Copyright (c) 2010-2015 Matt Bryson
11
  * Dual licensed under the MIT or GPL Version 2 licenses.
12
  *
55
  * - Added "all" fingers value to the fingers property, so any combination of fingers triggers the swipe, allowing event handlers to check the finger count
56
  *
57
  * $Date: 2012-09-08 (Thurs, 9 Aug 2012) $
58
+ * $version: 1.3.3 - Code tidy prep for min version
59
  *
60
  * $Date: 2012-04-10 (wed, 4 Oct 2012) $
61
  * $version: 1.4.0 - Added pinch support, pinchIn and pinchOut
62
  *
63
  * $Date: 2012-11-10 (Thurs, 11 Oct 2012) $
64
+ * $version: 1.5.0 - Added excludedElements, a jquery selector that specifies child elements that do NOT trigger swipes. By default, this is .noSwipe
65
  *
66
  * $Date: 2012-22-10 (Mon, 22 Oct 2012) $
67
  * $version: 1.5.1 - Fixed bug with jQuery 1.8 and trailing comma in excludedElements
101
  * $version 1.6.7 - Added patch from https://github.com/mattbryson/TouchSwipe-Jquery-Plugin/issues/206 to fix memory leak
102
  *
103
  * $Date: 2015-2-2 (Mon, 2 Feb 2015) $
104
+ * $version 1.6.8 - Added preventDefaultEvents option to proxy events regardless.
105
  * - Fixed issue with swipe and pinch not triggering at the same time
106
+ *
107
+ * $Date: 2015-9-6 (Tues, 9 June 2015) $
108
+ * $version 1.6.9 - Added PR from jdalton/hybrid to fix pointer events
109
+ * - Added scrolling demo
110
+ * - Added version property to plugin
111
+ *
112
+ * $Date: 2015-1-10 (Wed, 1 October 2015) $
113
+ * $version 1.6.10 - Added PR from beatspace to fix tap events
114
+ * $version 1.6.11 - Added PRs from indri-indri ( Doc tidyup), kkirsche ( Bower tidy up ), UziTech (preventDefaultEvents fixes )
115
+ * - Allowed setting multiple options via .swipe("options", options_hash) and more simply .swipe(options_hash) or exisitng instances
116
+ * $version 1.6.12 - Fixed bug with multi finger releases above 2 not triggering events
117
+ *
118
+ * $Date: 2015-12-18 (Fri, 18 December 2015) $
119
+ * $version 1.6.13 - Added PRs
120
+ * - Fixed #267 allowPageScroll not working correctly
121
+ * $version 1.6.14 - Fixed #220 / #248 doubletap not firing with swipes, #223 commonJS compatible
122
+ * $version 1.6.15 - More bug fixes
123
+ *
124
+ * $Date: 2016-04-29 (Fri, 29 April 2016) $
125
+ * $version 1.6.16 - Swipes with 0 distance now allow default events to trigger. So tapping any form elements or A tags will allow default interaction, but swiping will trigger a swipe.
126
+ * Removed the a, input, select etc from the excluded Children list as the 0 distance tap solves that issue.
127
+ * $Date: 2016-05-19 (Fri, 29 April 2016) $
128
+ * $version 1.6.17 - Fixed context issue when calling instance methods via $("selector").swipe("method");
129
+ * $version 1.6.18 - now honors fallbackToMouseEvents=false for MS Pointer events when a Mouse is used.
130
+ *
131
+ * $Date: 2018-09-17 (Mon, 17 September 2018) $
132
+ * $version 1.6.19 - replaced jQuery bind with on, replaced deprecated `navigator.pointerEvents` with `window.PointerEvents`
133
+
134
  */
135
 
136
  /**
151
  */
152
 
153
 
154
+ (function(factory) {
155
+ if (typeof define === 'function' && define.amd && define.amd.jQuery) {
156
+ // AMD. Register as anonymous module.
157
+ define(['jquery'], factory);
158
+ } else if (typeof module !== 'undefined' && module.exports) {
159
+ // CommonJS Module
160
+ factory(require("jquery"));
161
+ } else {
162
+ // Browser globals.
163
+ factory(jQuery);
164
+ }
165
+ }(function($) {
166
+ "use strict";
167
+
168
+ //Constants
169
+ var VERSION = "1.6.18",
170
+ LEFT = "left",
171
+ RIGHT = "right",
172
+ UP = "up",
173
+ DOWN = "down",
174
+ IN = "in",
175
+ OUT = "out",
176
+
177
+ NONE = "none",
178
+ AUTO = "auto",
179
+
180
+ SWIPE = "swipe",
181
+ PINCH = "pinch",
182
+ TAP = "tap",
183
+ DOUBLE_TAP = "doubletap",
184
+ LONG_TAP = "longtap",
185
+ HOLD = "hold",
186
+
187
+ HORIZONTAL = "horizontal",
188
+ VERTICAL = "vertical",
189
+
190
+ ALL_FINGERS = "all",
191
+
192
+ DOUBLE_TAP_THRESHOLD = 10,
193
+
194
+ PHASE_START = "start",
195
+ PHASE_MOVE = "move",
196
+ PHASE_END = "end",
197
+ PHASE_CANCEL = "cancel",
198
+
199
+ SUPPORTS_TOUCH = 'ontouchstart' in window,
200
+
201
+ SUPPORTS_POINTER_IE10 = window.navigator.msPointerEnabled && !window.PointerEvent && !SUPPORTS_TOUCH,
202
+
203
+ SUPPORTS_POINTER = (window.PointerEvent || window.navigator.msPointerEnabled) && !SUPPORTS_TOUCH,
204
+
205
+ PLUGIN_NS = 'TouchSwipe';
206
+
207
+
208
+
209
+ /**
210
+ * The default configuration, and available options to configure touch swipe with.
211
+ * You can set the default values by updating any of the properties prior to instantiation.
212
+ * @name $.fn.swipe.defaults
213
+ * @namespace
214
+ * @property {int} [fingers=1] The number of fingers to detect in a swipe. Any swipes that do not meet this requirement will NOT trigger swipe handlers.
215
+ * @property {int} [threshold=75] The number of pixels that the user must move their finger by before it is considered a swipe.
216
+ * @property {int} [cancelThreshold=null] The number of pixels that the user must move their finger back from the original swipe direction to cancel the gesture.
217
+ * @property {int} [pinchThreshold=20] The number of pixels that the user must pinch their finger by before it is considered a pinch.
218
+ * @property {int} [maxTimeThreshold=null] Time, in milliseconds, between touchStart and touchEnd must NOT exceed in order to be considered a swipe.
219
+ * @property {int} [fingerReleaseThreshold=250] Time in milliseconds between releasing multiple fingers. If 2 fingers are down, and are released one after the other, if they are within this threshold, it counts as a simultaneous release.
220
+ * @property {int} [longTapThreshold=500] Time in milliseconds between tap and release for a long tap
221
+ * @property {int} [doubleTapThreshold=200] Time in milliseconds between 2 taps to count as a double tap
222
+ * @property {function} [swipe=null] A handler to catch all swipes. See {@link $.fn.swipe#event:swipe}
223
+ * @property {function} [swipeLeft=null] A handler that is triggered for "left" swipes. See {@link $.fn.swipe#event:swipeLeft}
224
+ * @property {function} [swipeRight=null] A handler that is triggered for "right" swipes. See {@link $.fn.swipe#event:swipeRight}
225
+ * @property {function} [swipeUp=null] A handler that is triggered for "up" swipes. See {@link $.fn.swipe#event:swipeUp}
226
+ * @property {function} [swipeDown=null] A handler that is triggered for "down" swipes. See {@link $.fn.swipe#event:swipeDown}
227
+ * @property {function} [swipeStatus=null] A handler triggered for every phase of the swipe. See {@link $.fn.swipe#event:swipeStatus}
228
+ * @property {function} [pinchIn=null] A handler triggered for pinch in events. See {@link $.fn.swipe#event:pinchIn}
229
+ * @property {function} [pinchOut=null] A handler triggered for pinch out events. See {@link $.fn.swipe#event:pinchOut}
230
+ * @property {function} [pinchStatus=null] A handler triggered for every phase of a pinch. See {@link $.fn.swipe#event:pinchStatus}
231
+ * @property {function} [tap=null] A handler triggered when a user just taps on the item, rather than swipes it. If they do not move, tap is triggered, if they do move, it is not.
232
+ * @property {function} [doubleTap=null] A handler triggered when a user double taps on the item. The delay between taps can be set with the doubleTapThreshold property. See {@link $.fn.swipe.defaults#doubleTapThreshold}
233
+ * @property {function} [longTap=null] A handler triggered when a user long taps on the item. The delay between start and end can be set with the longTapThreshold property. See {@link $.fn.swipe.defaults#longTapThreshold}
234
+ * @property (function) [hold=null] A handler triggered when a user reaches longTapThreshold on the item. See {@link $.fn.swipe.defaults#longTapThreshold}
235
+ * @property {boolean} [triggerOnTouchEnd=true] If true, the swipe events are triggered when the touch end event is received (user releases finger). If false, it will be triggered on reaching the threshold, and then cancel the touch event automatically.
236
+ * @property {boolean} [triggerOnTouchLeave=false] If true, then when the user leaves the swipe object, the swipe will end and trigger appropriate handlers.
237
+ * @property {string|undefined} [allowPageScroll='auto'] How the browser handles page scrolls when the user is swiping on a touchSwipe object. See {@link $.fn.swipe.pageScroll}. <br/><br/>
238
+ <code>"auto"</code> : all undefined swipes will cause the page to scroll in that direction. <br/>
239
+ <code>"none"</code> : the page will not scroll when user swipes. <br/>
240
+ <code>"horizontal"</code> : will force page to scroll on horizontal swipes. <br/>
241
+ <code>"vertical"</code> : will force page to scroll on vertical swipes. <br/>
242
+ * @property {boolean} [fallbackToMouseEvents=true] If true mouse events are used when run on a non touch device, false will stop swipes being triggered by mouse events on non touch devices.
243
+ * @property {string} [excludedElements=".noSwipe"] A jquery selector that specifies child elements that do NOT trigger swipes. By default this excludes elements with the class .noSwipe .
244
+ * @property {boolean} [preventDefaultEvents=true] by default default events are cancelled, so the page doesn't move. You can disable this so both native events fire as well as your handlers.
245
+
246
+ */
247
+ var defaults = {
248
+ fingers: 1,
249
+ threshold: 75,
250
+ cancelThreshold: null,
251
+ pinchThreshold: 20,
252
+ maxTimeThreshold: null,
253
+ fingerReleaseThreshold: 250,
254
+ longTapThreshold: 500,
255
+ doubleTapThreshold: 200,
256
+ swipe: null,
257
+ swipeLeft: null,
258
+ swipeRight: null,
259
+ swipeUp: null,
260
+ swipeDown: null,
261
+ swipeStatus: null,
262
+ pinchIn: null,
263
+ pinchOut: null,
264
+ pinchStatus: null,
265
+ click: null, //Deprecated since 1.6.2
266
+ tap: null,
267
+ doubleTap: null,
268
+ longTap: null,
269
+ hold: null,
270
+ triggerOnTouchEnd: true,
271
+ triggerOnTouchLeave: false,
272
+ allowPageScroll: "auto",
273
+ fallbackToMouseEvents: true,
274
+ excludedElements: ".noSwipe",
275
+ preventDefaultEvents: true
276
+ };
277
+
278
+
279
+
280
+ /**
281
+ * Applies TouchSwipe behaviour to one or more jQuery objects.
282
+ * The TouchSwipe plugin can be instantiated via this method, or methods within
283
+ * TouchSwipe can be executed via this method as per jQuery plugin architecture.
284
+ * An existing plugin can have its options changed simply by re calling .swipe(options)
285
+ * @see TouchSwipe
286
+ * @class
287
+ * @param {Mixed} method If the current DOMNode is a TouchSwipe object, and <code>method</code> is a TouchSwipe method, then
288
+ * the <code>method</code> is executed, and any following arguments are passed to the TouchSwipe method.
289
+ * If <code>method</code> is an object, then the TouchSwipe class is instantiated on the current DOMNode, passing the
290
+ * configuration properties defined in the object. See TouchSwipe
291
+ *
292
+ */
293
+ $.fn.swipe = function(method) {
294
+ var $this = $(this),
295
+ plugin = $this.data(PLUGIN_NS);
296
+
297
+ //Check if we are already instantiated and trying to execute a method
298
+ if (plugin && typeof method === 'string') {
299
+ if (plugin[method]) {
300
+ return plugin[method].apply(plugin, Array.prototype.slice.call(arguments, 1));
301
+ } else {
302
+ $.error('Method ' + method + ' does not exist on jQuery.swipe');
303
+ }
304
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
 
306
+ //Else update existing plugin with new options hash
307
+ else if (plugin && typeof method === 'object') {
308
+ plugin['option'].apply(plugin, arguments);
309
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
 
311
+ //Else not instantiated and trying to pass init object (or nothing)
312
+ else if (!plugin && (typeof method === 'object' || !method)) {
313
+ return init.apply(this, arguments);
314
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
 
316
+ return $this;
317
+ };
318
+
319
+ /**
320
+ * The version of the plugin
321
+ * @readonly
322
+ */
323
+ $.fn.swipe.version = VERSION;
324
+
325
+
326
+
327
+ //Expose our defaults so a user could override the plugin defaults
328
+ $.fn.swipe.defaults = defaults;
329
+
330
+ /**
331
+ * The phases that a touch event goes through. The <code>phase</code> is passed to the event handlers.
332
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
333
+ * @namespace
334
+ * @readonly
335
+ * @property {string} PHASE_START Constant indicating the start phase of the touch event. Value is <code>"start"</code>.
336
+ * @property {string} PHASE_MOVE Constant indicating the move phase of the touch event. Value is <code>"move"</code>.
337
+ * @property {string} PHASE_END Constant indicating the end phase of the touch event. Value is <code>"end"</code>.
338
+ * @property {string} PHASE_CANCEL Constant indicating the cancel phase of the touch event. Value is <code>"cancel"</code>.
339
+ */
340
+ $.fn.swipe.phases = {
341
+ PHASE_START: PHASE_START,
342
+ PHASE_MOVE: PHASE_MOVE,
343
+ PHASE_END: PHASE_END,
344
+ PHASE_CANCEL: PHASE_CANCEL
345
+ };
346
+
347
+ /**
348
+ * The direction constants that are passed to the event handlers.
349
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
350
+ * @namespace
351
+ * @readonly
352
+ * @property {string} LEFT Constant indicating the left direction. Value is <code>"left"</code>.
353
+ * @property {string} RIGHT Constant indicating the right direction. Value is <code>"right"</code>.
354
+ * @property {string} UP Constant indicating the up direction. Value is <code>"up"</code>.
355
+ * @property {string} DOWN Constant indicating the down direction. Value is <code>"cancel"</code>.
356
+ * @property {string} IN Constant indicating the in direction. Value is <code>"in"</code>.
357
+ * @property {string} OUT Constant indicating the out direction. Value is <code>"out"</code>.
358
+ */
359
+ $.fn.swipe.directions = {
360
+ LEFT: LEFT,
361
+ RIGHT: RIGHT,
362
+ UP: UP,
363
+ DOWN: DOWN,
364
+ IN: IN,
365
+ OUT: OUT
366
+ };
367
+
368
+ /**
369
+ * The page scroll constants that can be used to set the value of <code>allowPageScroll</code> option
370
+ * These properties are read only
371
+ * @namespace
372
+ * @readonly
373
+ * @see $.fn.swipe.defaults#allowPageScroll
374
+ * @property {string} NONE Constant indicating no page scrolling is allowed. Value is <code>"none"</code>.
375
+ * @property {string} HORIZONTAL Constant indicating horizontal page scrolling is allowed. Value is <code>"horizontal"</code>.
376
+ * @property {string} VERTICAL Constant indicating vertical page scrolling is allowed. Value is <code>"vertical"</code>.
377
+ * @property {string} AUTO Constant indicating either horizontal or vertical will be allowed, depending on the swipe handlers registered. Value is <code>"auto"</code>.
378
+ */
379
+ $.fn.swipe.pageScroll = {
380
+ NONE: NONE,
381
+ HORIZONTAL: HORIZONTAL,
382
+ VERTICAL: VERTICAL,
383
+ AUTO: AUTO
384
+ };
385
+
386
+ /**
387
+ * Constants representing the number of fingers used in a swipe. These are used to set both the value of <code>fingers</code> in the
388
+ * options object, as well as the value of the <code>fingers</code> event property.
389
+ * These properties are read only, attempting to change them will not alter the values passed to the event handlers.
390
+ * @namespace
391
+ * @readonly
392
+ * @see $.fn.swipe.defaults#fingers
393
+ * @property {string} ONE Constant indicating 1 finger is to be detected / was detected. Value is <code>1</code>.
394
+ * @property {string} TWO Constant indicating 2 fingers are to be detected / were detected. Value is <code>2</code>.
395
+ * @property {string} THREE Constant indicating 3 finger are to be detected / were detected. Value is <code>3</code>.
396
+ * @property {string} FOUR Constant indicating 4 finger are to be detected / were detected. Not all devices support this. Value is <code>4</code>.
397
+ * @property {string} FIVE Constant indicating 5 finger are to be detected / were detected. Not all devices support this. Value is <code>5</code>.
398
+ * @property {string} ALL Constant indicating any combination of finger are to be detected. Value is <code>"all"</code>.
399
+ */
400
+ $.fn.swipe.fingers = {
401
+ ONE: 1,
402
+ TWO: 2,
403
+ THREE: 3,
404
+ FOUR: 4,
405
+ FIVE: 5,
406
+ ALL: ALL_FINGERS
407
+ };
408
+
409
+ /**
410
+ * Initialise the plugin for each DOM element matched
411
+ * This creates a new instance of the main TouchSwipe class for each DOM element, and then
412
+ * saves a reference to that instance in the elements data property.
413
+ * @internal
414
+ */
415
+ function init(options) {
416
+ //Prep and extend the options
417
+ if (options && (options.allowPageScroll === undefined && (options.swipe !== undefined || options.swipeStatus !== undefined))) {
418
+ options.allowPageScroll = NONE;
419
+ }
420
 
421
+ //Check for deprecated options
422
+ //Ensure that any old click handlers are assigned to the new tap, unless we have a tap
423
+ if (options.click !== undefined && options.tap === undefined) {
424
+ options.tap = options.click;
425
+ }
426
 
427
+ if (!options) {
428
+ options = {};
429
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
 
431
+ //pass empty object so we dont modify the defaults
432
+ options = $.extend({}, $.fn.swipe.defaults, options);
433
+
434
+ //For each element instantiate the plugin
435
+ return this.each(function() {
436
+ var $this = $(this);
437
+
438
+ //Check we havent already initialised the plugin
439
+ var plugin = $this.data(PLUGIN_NS);
440
+
441
+ if (!plugin) {
442
+ plugin = new TouchSwipe(this, options);
443
+ $this.data(PLUGIN_NS, plugin);
444
+ }
445
+ });
446
+ }
447
+
448
+ /**
449
+ * Main TouchSwipe Plugin Class.
450
+ * Do not use this to construct your TouchSwipe object, use the jQuery plugin method $.fn.swipe(); {@link $.fn.swipe}
451
+ * @private
452
+ * @name TouchSwipe
453
+ * @param {DOMNode} element The HTML DOM object to apply to plugin to
454
+ * @param {Object} options The options to configure the plugin with. @link {$.fn.swipe.defaults}
455
+ * @see $.fh.swipe.defaults
456
+ * @see $.fh.swipe
457
+ * @class
458
+ */
459
+ function TouchSwipe(element, options) {
460
+
461
+ //take a local/instacne level copy of the options - should make it this.options really...
462
+ var options = $.extend({}, options);
463
+
464
+ var useTouchEvents = (SUPPORTS_TOUCH || SUPPORTS_POINTER || !options.fallbackToMouseEvents),
465
+ START_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerDown' : 'pointerdown') : 'touchstart') : 'mousedown',
466
+ MOVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerMove' : 'pointermove') : 'touchmove') : 'mousemove',
467
+ END_EV = useTouchEvents ? (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerUp' : 'pointerup') : 'touchend') : 'mouseup',
468
+ LEAVE_EV = useTouchEvents ? (SUPPORTS_POINTER ? 'mouseleave' : null) : 'mouseleave', //we manually detect leave on touch devices, so null event here
469
+ CANCEL_EV = (SUPPORTS_POINTER ? (SUPPORTS_POINTER_IE10 ? 'MSPointerCancel' : 'pointercancel') : 'touchcancel');
470
+
471
+
472
+
473
+ //touch properties
474
+ var distance = 0,
475
+ direction = null,
476
+ currentDirection = null,
477
+ duration = 0,
478
+ startTouchesDistance = 0,
479
+ endTouchesDistance = 0,
480
+ pinchZoom = 1,
481
+ pinchDistance = 0,
482
+ pinchDirection = 0,
483
+ maximumsMap = null;
484
+
485
+
486
+
487
+ //jQuery wrapped element for this instance
488
+ var $element = $(element);
489
+
490
+ //Current phase of th touch cycle
491
+ var phase = "start";
492
+
493
+ // the current number of fingers being used.
494
+ var fingerCount = 0;
495
+
496
+ //track mouse points / delta
497
+ var fingerData = {};
498
+
499
+ //track times
500
+ var startTime = 0,
501
+ endTime = 0,
502
+ previousTouchEndTime = 0,
503
+ fingerCountAtRelease = 0,
504
+ doubleTapStartTime = 0;
505
+
506
+ //Timeouts
507
+ var singleTapTimeout = null,
508
+ holdTimeout = null;
509
+
510
+ // Add gestures to all swipable areas if supported
511
+ try {
512
+ $element.on(START_EV, touchStart);
513
+ $element.on(CANCEL_EV, touchCancel);
514
+ } catch (e) {
515
+ $.error('events not supported ' + START_EV + ',' + CANCEL_EV + ' on jQuery.swipe');
516
+ }
517
 
518
+ //
519
+ //Public methods
520
+ //
521
 
522
  /**
523
+ * re-enables the swipe plugin with the previous configuration
524
+ * @function
525
+ * @name $.fn.swipe#enable
526
+ * @return {DOMNode} The Dom element that was registered with TouchSwipe
527
+ * @example $("#element").swipe("enable");
 
 
 
528
  */
529
+ this.enable = function() {
530
+ //Incase we are already enabled, clean up...
531
+ this.disable();
532
+ $element.on(START_EV, touchStart);
533
+ $element.on(CANCEL_EV, touchCancel);
534
+ return $element;
535
  };
536
 
537
  /**
538
+ * disables the swipe plugin
539
+ * @function
540
+ * @name $.fn.swipe#disable
541
+ * @return {DOMNode} The Dom element that is now registered with TouchSwipe
542
+ * @example $("#element").swipe("disable");
 
 
 
 
 
543
  */
544
+ this.disable = function() {
545
+ removeListeners();
546
+ return $element;
 
 
 
 
547
  };
548
 
549
  /**
550
+ * Destroy the swipe plugin completely. To use any swipe methods, you must re initialise the plugin.
551
+ * @function
552
+ * @name $.fn.swipe#destroy
553
+ * @example $("#element").swipe("destroy");
 
 
 
 
 
554
  */
555
+ this.destroy = function() {
556
+ removeListeners();
557
+ $element.data(PLUGIN_NS, null);
558
+ $element = null;
 
559
  };
560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
 
562
  /**
563
+ * Allows run time updating of the swipe configuration options.
564
+ * @function
565
+ * @name $.fn.swipe#option
566
+ * @param {String} property The option property to get or set, or a has of multiple options to set
567
+ * @param {Object} [value] The value to set the property to
568
+ * @return {Object} If only a property name is passed, then that property value is returned. If nothing is passed the current options hash is returned.
569
+ * @example $("#element").swipe("option", "threshold"); // return the threshold
570
+ * @example $("#element").swipe("option", "threshold", 100); // set the threshold after init
571
+ * @example $("#element").swipe("option", {threshold:100, fingers:3} ); // set multiple properties after init
572
+ * @example $("#element").swipe({threshold:100, fingers:3} ); // set multiple properties after init - the "option" method is optional!
573
+ * @example $("#element").swipe("option"); // Return the current options hash
574
+ * @see $.fn.swipe.defaults
575
+ *
576
  */
577
+ this.option = function(property, value) {
578
+
579
+ if (typeof property === 'object') {
580
+ options = $.extend(options, property);
581
+ } else if (options[property] !== undefined) {
582
+ if (value === undefined) {
583
+ return options[property];
584
+ } else {
585
+ options[property] = value;
 
586
  }
587
+ } else if (!property) {
588
+ return options;
589
+ } else {
590
+ $.error('Option ' + property + ' does not exist on jQuery.swipe.options');
591
+ }
592
 
593
+ return null;
594
+ }
 
 
 
 
595
 
 
 
 
596
 
 
 
597
 
598
+ //
599
+ // Private methods
600
+ //
 
 
 
601
 
602
+ //
603
+ // EVENTS
604
+ //
605
  /**
606
+ * Event handler for a touch start event.
607
+ * Stops the default click event from triggering and stores where we touched
608
+ * @inner
609
+ * @param {object} jqEvent The normalised jQuery event object.
 
 
 
 
 
610
  */
611
+ function touchStart(jqEvent) {
612
+
613
+ //If we already in a touch event (a finger already in use) then ignore subsequent ones..
614
+ if (getTouchInProgress()) {
615
+ return;
616
+ }
617
+
618
+ //Check if this element matches any in the excluded elements selectors, or its parent is excluded, if so, DON'T swipe
619
+ if ($(jqEvent.target).closest(options.excludedElements, $element).length > 0) {
620
+ return;
621
+ }
622
+
623
+ //As we use Jquery bind for events, we need to target the original event object
624
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
625
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
626
+
627
+
628
+ //If we have a pointer event, whoes type is 'mouse' and we have said NO mouse events, then dont do anything.
629
+ if(event.pointerType && event.pointerType=="mouse" && options.fallbackToMouseEvents==false) {
630
+ return;
631
+ };
632
+
633
+ var ret,
634
+ touches = event.touches,
635
+ evt = touches ? touches[0] : event;
636
+
637
+ phase = PHASE_START;
638
+
639
+ //If we support touches, get the finger count
640
+ if (touches) {
641
+ // get the total number of fingers touching the screen
642
+ fingerCount = touches.length;
643
+ }
644
+ //Else this is the desktop, so stop the browser from dragging content
645
+ else if (options.preventDefaultEvents !== false) {
646
+ jqEvent.preventDefault(); //call this on jq event so we are cross browser
647
+ }
648
+
649
+ //clear vars..
650
+ distance = 0;
651
+ direction = null;
652
+ currentDirection=null;
653
+ pinchDirection = null;
654
+ duration = 0;
655
+ startTouchesDistance = 0;
656
+ endTouchesDistance = 0;
657
+ pinchZoom = 1;
658
+ pinchDistance = 0;
659
+ maximumsMap = createMaximumsData();
660
+ cancelMultiFingerRelease();
661
+
662
+ //Create the default finger data
663
+ createFingerData(0, evt);
664
+
665
+ // check the number of fingers is what we are looking for, or we are capturing pinches
666
+ if (!touches || (fingerCount === options.fingers || options.fingers === ALL_FINGERS) || hasPinches()) {
667
+ // get the coordinates of the touch
668
+ startTime = getTimeStamp();
669
+
670
+ if (fingerCount == 2) {
671
+ //Keep track of the initial pinch distance, so we can calculate the diff later
672
+ //Store second finger data as start
673
+ createFingerData(1, touches[1]);
674
+ startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
675
  }
676
 
677
+ if (options.swipeStatus || options.pinchStatus) {
678
+ ret = triggerHandler(event, phase);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
  }
680
+ } else {
681
+ //A touch with more or less than the fingers we are looking for, so cancel
682
+ ret = false;
683
+ }
684
+
685
+ //If we have a return value from the users handler, then return and cancel
686
+ if (ret === false) {
687
+ phase = PHASE_CANCEL;
688
+ triggerHandler(event, phase);
689
+ return ret;
690
+ } else {
691
+ if (options.hold) {
692
+ holdTimeout = setTimeout($.proxy(function() {
693
+ //Trigger the event
694
+ $element.trigger('hold', [event.target]);
695
+ //Fire the callback
696
+ if (options.hold) {
697
+ ret = options.hold.call($element, event, event.target);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
698
  }
699
+ }, this), options.longTapThreshold);
700
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701
 
702
+ setTouchInProgress(true);
703
+ }
 
704
 
705
+ return null;
706
+ };
 
707
 
 
 
708
 
709
 
710
+ /**
711
+ * Event handler for a touch move event.
712
+ * If we change fingers during move, then cancel the event
713
+ * @inner
714
+ * @param {object} jqEvent The normalised jQuery event object.
715
+ */
716
+ function touchMove(jqEvent) {
717
 
718
+ //As we use Jquery bind for events, we need to target the original event object
719
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
720
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
721
 
722
+ //If we are ending, cancelling, or within the threshold of 2 fingers being released, don't track anything..
723
+ if (phase === PHASE_END || phase === PHASE_CANCEL || inMultiFingerRelease())
724
+ return;
725
 
726
+ var ret,
727
+ touches = event.touches,
728
+ evt = touches ? touches[0] : event;
729
 
 
 
730
 
731
+ //Update the finger data
732
+ var currentFinger = updateFingerData(evt);
733
+ endTime = getTimeStamp();
 
 
734
 
735
+ if (touches) {
736
+ fingerCount = touches.length;
737
+ }
 
738
 
739
+ if (options.hold) {
740
+ clearTimeout(holdTimeout);
741
+ }
742
 
743
+ phase = PHASE_MOVE;
744
 
745
+ //If we have 2 fingers get Touches distance as well
746
+ if (fingerCount == 2) {
 
747
 
748
+ //Keep track of the initial pinch distance, so we can calculate the diff later
749
+ //We do this here as well as the start event, in case they start with 1 finger, and the press 2 fingers
750
+ if (startTouchesDistance == 0) {
751
+ //Create second finger if this is the first time...
752
+ createFingerData(1, touches[1]);
753
 
754
+ startTouchesDistance = endTouchesDistance = calculateTouchesDistance(fingerData[0].start, fingerData[1].start);
755
+ } else {
756
+ //Else just update the second finger
757
+ updateFingerData(touches[1]);
758
 
759
+ endTouchesDistance = calculateTouchesDistance(fingerData[0].end, fingerData[1].end);
760
+ pinchDirection = calculatePinchDirection(fingerData[0].end, fingerData[1].end);
761
+ }
762
 
763
+ pinchZoom = calculatePinchZoom(startTouchesDistance, endTouchesDistance);
764
+ pinchDistance = Math.abs(startTouchesDistance - endTouchesDistance);
765
+ }
766
 
767
+ if ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !touches || hasPinches()) {
768
 
769
+ //The overall direction of the swipe. From start to now.
770
+ direction = calculateDirection(currentFinger.start, currentFinger.end);
771
 
772
+ //The immediate direction of the swipe, direction between the last movement and this one.
773
+ currentDirection = calculateDirection(currentFinger.last, currentFinger.end);
 
774
 
775
+ //Check if we need to prevent default event (page scroll / pinch zoom) or not
776
+ validateDefaultEvent(jqEvent, currentDirection);
777
 
778
+ //Distance and duration are all off the main finger
779
+ distance = calculateDistance(currentFinger.start, currentFinger.end);
780
+ duration = calculateDuration();
781
 
782
+ //Cache the maximum distance we made in this direction
783
+ setMaxDistance(direction, distance);
 
784
 
785
+ //Trigger status handler
786
+ ret = triggerHandler(event, phase);
787
 
 
 
788
 
789
+ //If we trigger end events when threshold are met, or trigger events when touch leaves element
790
+ if (!options.triggerOnTouchEnd || options.triggerOnTouchLeave) {
791
 
792
+ var inBounds = true;
 
 
 
 
793
 
794
+ //If checking if we leave the element, run the bounds check (we can use touchleave as its not supported on webkit)
795
+ if (options.triggerOnTouchLeave) {
796
+ var bounds = getbounds(this);
797
+ inBounds = isInBounds(currentFinger.end, bounds);
798
+ }
 
 
 
799
 
800
+ //Trigger end handles as we swipe if thresholds met or if we have left the element if the user has asked to check these..
801
+ if (!options.triggerOnTouchEnd && inBounds) {
802
+ phase = getNextPhase(PHASE_MOVE);
803
+ }
804
+ //We end if out of bounds here, so set current phase to END, and check if its modified
805
+ else if (options.triggerOnTouchLeave && !inBounds) {
806
+ phase = getNextPhase(PHASE_END);
807
+ }
 
808
 
809
+ if (phase == PHASE_CANCEL || phase == PHASE_END) {
810
+ triggerHandler(event, phase);
811
+ }
 
812
  }
813
+ } else {
814
+ phase = PHASE_CANCEL;
815
+ triggerHandler(event, phase);
816
+ }
817
+
818
+ if (ret === false) {
819
+ phase = PHASE_CANCEL;
820
+ triggerHandler(event, phase);
821
+ }
822
+ }
823
 
824
 
825
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
826
 
827
+ /**
828
+ * Event handler for a touch end event.
829
+ * Calculate the direction and trigger events
830
+ * @inner
831
+ * @param {object} jqEvent The normalised jQuery event object.
832
+ */
833
+ function touchEnd(jqEvent) {
834
+ //As we use Jquery bind for events, we need to target the original event object
835
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
836
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent,
837
+ touches = event.touches;
838
+
839
+ //If we are still in a touch with the device wait a fraction and see if the other finger comes up
840
+ //if it does within the threshold, then we treat it as a multi release, not a single release and end the touch / swipe
841
+ if (touches) {
842
+ if (touches.length && !inMultiFingerRelease()) {
843
+ startMultiFingerRelease(event);
844
+ return true;
845
+ } else if (touches.length && inMultiFingerRelease()) {
846
+ return true;
847
  }
848
+ }
849
+
850
+ //If a previous finger has been released, check how long ago, if within the threshold, then assume it was a multifinger release.
851
+ //This is used to allow 2 fingers to release fractionally after each other, whilst maintaining the event as containing 2 fingers, not 1
852
+ if (inMultiFingerRelease()) {
853
+ fingerCount = fingerCountAtRelease;
854
+ }
855
+
856
+ //Set end of swipe
857
+ endTime = getTimeStamp();
858
+
859
+ //Get duration incase move was never fired
860
+ duration = calculateDuration();
861
+
862
+ //If we trigger handlers at end of swipe OR, we trigger during, but they didnt trigger and we are still in the move phase
863
+ if (didSwipeBackToCancel() || !validateSwipeDistance()) {
864
+ phase = PHASE_CANCEL;
865
+ triggerHandler(event, phase);
866
+ } else if (options.triggerOnTouchEnd || (options.triggerOnTouchEnd === false && phase === PHASE_MOVE)) {
867
+ //call this on jq event so we are cross browser
868
+ if (options.preventDefaultEvents !== false && jqEvent.cancelable !== false) {
869
+ jqEvent.preventDefault();
870
  }
871
+ phase = PHASE_END;
872
+ triggerHandler(event, phase);
873
+ }
874
+ //Special cases - A tap should always fire on touch end regardless,
875
+ //So here we manually trigger the tap end handler by itself
876
+ //We dont run trigger handler as it will re-trigger events that may have fired already
877
+ else if (!options.triggerOnTouchEnd && hasTap()) {
878
+ //Trigger the pinch events...
879
+ phase = PHASE_END;
880
+ triggerHandlerForGesture(event, phase, TAP);
881
+ } else if (phase === PHASE_MOVE) {
882
+ phase = PHASE_CANCEL;
883
+ triggerHandler(event, phase);
884
+ }
885
+
886
+ setTouchInProgress(false);
887
+
888
+ return null;
889
+ }
890
 
891
 
 
 
 
 
 
 
 
 
892
 
893
+ /**
894
+ * Event handler for a touch cancel event.
895
+ * Clears current vars
896
+ * @inner
897
+ */
898
+ function touchCancel() {
899
+ // reset the variables back to default values
900
+ fingerCount = 0;
901
+ endTime = 0;
902
+ startTime = 0;
903
+ startTouchesDistance = 0;
904
+ endTouchesDistance = 0;
905
+ pinchZoom = 1;
906
+
907
+ //If we were in progress of tracking a possible multi touch end, then re set it.
908
+ cancelMultiFingerRelease();
909
+
910
+ setTouchInProgress(false);
911
+ }
912
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
913
 
914
+ /**
915
+ * Event handler for a touch leave event.
916
+ * This is only triggered on desktops, in touch we work this out manually
917
+ * as the touchleave event is not supported in webkit
918
+ * @inner
919
+ */
920
+ function touchLeave(jqEvent) {
921
+ //If these events are being programmatically triggered, we don't have an original event object, so use the Jq one.
922
+ var event = jqEvent.originalEvent ? jqEvent.originalEvent : jqEvent;
923
+
924
+ //If we have the trigger on leave property set....
925
+ if (options.triggerOnTouchLeave) {
926
+ phase = getNextPhase(PHASE_END);
927
+ triggerHandler(event, phase);
928
+ }
929
+ }
930
 
931
+ /**
932
+ * Removes all listeners that were associated with the plugin
933
+ * @inner
934
+ */
935
+ function removeListeners() {
936
+ $element.off(START_EV, touchStart);
937
+ $element.off(CANCEL_EV, touchCancel);
938
+ $element.off(MOVE_EV, touchMove);
939
+ $element.off(END_EV, touchEnd);
940
+
941
+ //we only have leave events on desktop, we manually calculate leave on touch as its not supported in webkit
942
+ if (LEAVE_EV) {
943
+ $element.off(LEAVE_EV, touchLeave);
944
+ }
945
+
946
+ setTouchInProgress(false);
947
+ }
948
 
 
 
 
 
949
 
950
+ /**
951
+ * Checks if the time and distance thresholds have been met, and if so then the appropriate handlers are fired.
952
+ */
953
+ function getNextPhase(currentPhase) {
954
+
955
+ var nextPhase = currentPhase;
956
+
957
+ // Ensure we have valid swipe (under time and over distance and check if we are out of bound...)
958
+ var validTime = validateSwipeTime();
959
+ var validDistance = validateSwipeDistance();
960
+ var didCancel = didSwipeBackToCancel();
961
+
962
+ //If we have exceeded our time, then cancel
963
+ if (!validTime || didCancel) {
964
+ nextPhase = PHASE_CANCEL;
965
+ }
966
+ //Else if we are moving, and have reached distance then end
967
+ else if (validDistance && currentPhase == PHASE_MOVE && (!options.triggerOnTouchEnd || options.triggerOnTouchLeave)) {
968
+ nextPhase = PHASE_END;
969
+ }
970
+ //Else if we have ended by leaving and didn't reach distance, then cancel
971
+ else if (!validDistance && currentPhase == PHASE_END && options.triggerOnTouchLeave) {
972
+ nextPhase = PHASE_CANCEL;
973
+ }
974
+
975
+ return nextPhase;
976
+ }
977
 
 
 
 
 
978
 
979
+ /**
980
+ * Trigger the relevant event handler
981
+ * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
982
+ * @param {object} event the original event object
983
+ * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
984
+ * @inner
985
+ */
986
+ function triggerHandler(event, phase) {
 
 
 
 
987
 
 
 
988
 
989
 
990
+ var ret,
991
+ touches = event.touches;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
992
 
993
+ // SWIPE GESTURES
994
+ if (didSwipe() || hasSwipes()) {
995
+ ret = triggerHandlerForGesture(event, phase, SWIPE);
996
+ }
997
 
998
+ // PINCH GESTURES (if the above didn't cancel)
999
+ if ((didPinch() || hasPinches()) && ret !== false) {
1000
+ ret = triggerHandlerForGesture(event, phase, PINCH);
1001
+ }
1002
 
1003
+ // CLICK / TAP (if the above didn't cancel)
1004
+ if (didDoubleTap() && ret !== false) {
1005
+ //Trigger the tap events...
1006
+ ret = triggerHandlerForGesture(event, phase, DOUBLE_TAP);
1007
+ }
1008
 
1009
+ // CLICK / TAP (if the above didn't cancel)
1010
+ else if (didLongTap() && ret !== false) {
1011
+ //Trigger the tap events...
1012
+ ret = triggerHandlerForGesture(event, phase, LONG_TAP);
1013
+ }
 
 
 
 
 
 
 
1014
 
1015
+ // CLICK / TAP (if the above didn't cancel)
1016
+ else if (didTap() && ret !== false) {
1017
+ //Trigger the tap event..
1018
+ ret = triggerHandlerForGesture(event, phase, TAP);
1019
+ }
1020
 
1021
 
1022
 
1023
+ // If we are cancelling the gesture, then manually trigger the reset handler
1024
+ if (phase === PHASE_CANCEL) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1025
 
1026
+ touchCancel(event);
1027
+ }
1028
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1029
 
1030
 
1031
 
1032
+ // If we are ending the gesture, then manually trigger the reset handler IF all fingers are off
1033
+ if (phase === PHASE_END) {
1034
+ //If we support touch, then check that all fingers are off before we cancel
1035
+ if (touches) {
1036
+ if (!touches.length) {
1037
+ touchCancel(event);
1038
+ }
1039
+ } else {
1040
+ touchCancel(event);
1041
+ }
1042
+ }
1043
 
1044
+ return ret;
1045
+ }
1046
 
 
 
1047
 
1048
 
1049
+ /**
1050
+ * Trigger the relevant event handler
1051
+ * The handlers are passed the original event, the element that was swiped, and in the case of the catch all handler, the direction that was swiped, "left", "right", "up", or "down"
1052
+ * @param {object} event the original event object
1053
+ * @param {string} phase the phase of the swipe (start, end cancel etc) {@link $.fn.swipe.phases}
1054
+ * @param {string} gesture the gesture to trigger a handler for : PINCH or SWIPE {@link $.fn.swipe.gestures}
1055
+ * @return Boolean False, to indicate that the event should stop propagation, or void.
1056
+ * @inner
1057
+ */
1058
+ function triggerHandlerForGesture(event, phase, gesture) {
1059
 
1060
+ var ret;
 
 
 
1061
 
1062
+ //SWIPES....
1063
+ if (gesture == SWIPE) {
1064
+ //Trigger status every time..
1065
+ $element.trigger('swipeStatus', [phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData, currentDirection]);
 
 
1066
 
1067
+ if (options.swipeStatus) {
1068
+ ret = options.swipeStatus.call($element, event, phase, direction || null, distance || 0, duration || 0, fingerCount, fingerData, currentDirection);
1069
+ //If the status cancels, then dont run the subsequent event handlers..
1070
+ if (ret === false) return false;
1071
+ }
1072
 
1073
+ if (phase == PHASE_END && validateSwipe()) {
 
 
 
 
1074
 
1075
+ //Cancel any taps that were in progress...
1076
+ clearTimeout(singleTapTimeout);
1077
+ clearTimeout(holdTimeout);
1078
 
1079
+ $element.trigger('swipe', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
 
1080
 
1081
+ if (options.swipe) {
1082
+ ret = options.swipe.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1083
+ //If the status cancels, then dont run the subsequent event handlers..
1084
+ if (ret === false) return false;
1085
+ }
1086
 
1087
+ //trigger direction specific event handlers
1088
+ switch (direction) {
1089
+ case LEFT:
1090
+ $element.trigger('swipeLeft', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
 
 
 
1091
 
1092
+ if (options.swipeLeft) {
1093
+ ret = options.swipeLeft.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1094
+ }
1095
+ break;
 
1096
 
1097
+ case RIGHT:
1098
+ $element.trigger('swipeRight', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
1099
 
1100
+ if (options.swipeRight) {
1101
+ ret = options.swipeRight.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1102
+ }
1103
+ break;
 
 
1104
 
1105
+ case UP:
1106
+ $element.trigger('swipeUp', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
 
 
 
1107
 
1108
+ if (options.swipeUp) {
1109
+ ret = options.swipeUp.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1110
+ }
1111
+ break;
1112
 
1113
+ case DOWN:
1114
+ $element.trigger('swipeDown', [direction, distance, duration, fingerCount, fingerData, currentDirection]);
 
 
 
 
1115
 
1116
+ if (options.swipeDown) {
1117
+ ret = options.swipeDown.call($element, event, direction, distance, duration, fingerCount, fingerData, currentDirection);
1118
+ }
1119
+ break;
1120
+ }
1121
  }
1122
+ }
1123
 
1124
 
1125
+ //PINCHES....
1126
+ if (gesture == PINCH) {
1127
+ $element.trigger('pinchStatus', [phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1128
 
1129
+ if (options.pinchStatus) {
1130
+ ret = options.pinchStatus.call($element, event, phase, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1131
+ //If the status cancels, then dont run the subsequent event handlers..
1132
+ if (ret === false) return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
  }
1134
 
1135
+ if (phase == PHASE_END && validatePinch()) {
 
 
 
 
 
 
 
 
 
 
1136
 
1137
+ switch (pinchDirection) {
1138
+ case IN:
1139
+ $element.trigger('pinchIn', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
1140
 
1141
+ if (options.pinchIn) {
1142
+ ret = options.pinchIn.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1143
+ }
1144
+ break;
 
 
 
 
 
 
 
 
1145
 
1146
+ case OUT:
1147
+ $element.trigger('pinchOut', [pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1148
 
1149
+ if (options.pinchOut) {
1150
+ ret = options.pinchOut.call($element, event, pinchDirection || null, pinchDistance || 0, duration || 0, fingerCount, pinchZoom, fingerData);
1151
+ }
1152
+ break;
1153
+ }
1154
  }
1155
+ }
1156
+
1157
+ if (gesture == TAP) {
1158
+ if (phase === PHASE_CANCEL || phase === PHASE_END) {
1159
+
1160
+ clearTimeout(singleTapTimeout);
1161
+ clearTimeout(holdTimeout);
1162
+
1163
+ //If we are also looking for doubelTaps, wait incase this is one...
1164
+ if (hasDoubleTap() && !inDoubleTap()) {
1165
+ doubleTapStartTime = getTimeStamp();
1166
+
1167
+ //Now wait for the double tap timeout, and trigger this single tap
1168
+ //if its not cancelled by a double tap
1169
+ singleTapTimeout = setTimeout($.proxy(function() {
1170
+ doubleTapStartTime = null;
1171
+ $element.trigger('tap', [event.target]);
1172
+
1173
+ if (options.tap) {
1174
+ ret = options.tap.call($element, event, event.target);
1175
+ }
1176
+ }, this), options.doubleTapThreshold);
1177
+
1178
+ } else {
1179
+ doubleTapStartTime = null;
1180
+ $element.trigger('tap', [event.target]);
1181
+ if (options.tap) {
1182
+ ret = options.tap.call($element, event, event.target);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1183
  }
1184
+ }
1185
  }
1186
+ } else if (gesture == DOUBLE_TAP) {
1187
+ if (phase === PHASE_CANCEL || phase === PHASE_END) {
1188
+ clearTimeout(singleTapTimeout);
1189
+ clearTimeout(holdTimeout);
1190
+ doubleTapStartTime = null;
1191
+ $element.trigger('doubletap', [event.target]);
1192
+
1193
+ if (options.doubleTap) {
1194
+ ret = options.doubleTap.call($element, event, event.target);
1195
+ }
 
 
 
 
1196
  }
1197
+ } else if (gesture == LONG_TAP) {
1198
+ if (phase === PHASE_CANCEL || phase === PHASE_END) {
1199
+ clearTimeout(singleTapTimeout);
1200
+ doubleTapStartTime = null;
1201
+
1202
+ $element.trigger('longtap', [event.target]);
1203
+ if (options.longTap) {
1204
+ ret = options.longTap.call($element, event, event.target);
1205
+ }
 
 
 
 
 
 
 
 
 
 
1206
  }
1207
+ }
1208
 
1209
+ return ret;
1210
+ }
1211
 
1212
 
1213
+ //
1214
+ // GESTURE VALIDATION
1215
+ //
1216
 
1217
+ /**
1218
+ * Checks the user has swipe far enough
1219
+ * @return Boolean if <code>threshold</code> has been set, return true if the threshold was met, else false.
1220
+ * If no threshold was set, then we return true.
1221
+ * @inner
1222
+ */
1223
+ function validateSwipeDistance() {
1224
+ var valid = true;
1225
+ //If we made it past the min swipe distance..
1226
+ if (options.threshold !== null) {
1227
+ valid = distance >= options.threshold;
1228
+ }
1229
+
1230
+ return valid;
1231
+ }
 
 
 
 
 
1232
 
1233
+ /**
1234
+ * Checks the user has swiped back to cancel.
1235
+ * @return Boolean if <code>cancelThreshold</code> has been set, return true if the cancelThreshold was met, else false.
1236
+ * If no cancelThreshold was set, then we return true.
1237
+ * @inner
1238
+ */
1239
+ function didSwipeBackToCancel() {
1240
+ var cancelled = false;
1241
+ if (options.cancelThreshold !== null && direction !== null) {
1242
+ cancelled = (getMaxDistance(direction) - distance) >= options.cancelThreshold;
1243
+ }
1244
 
1245
+ return cancelled;
1246
+ }
1247
 
1248
+ /**
1249
+ * Checks the user has pinched far enough
1250
+ * @return Boolean if <code>pinchThreshold</code> has been set, return true if the threshold was met, else false.
1251
+ * If no threshold was set, then we return true.
1252
+ * @inner
1253
+ */
1254
+ function validatePinchDistance() {
1255
+ if (options.pinchThreshold !== null) {
1256
+ return pinchDistance >= options.pinchThreshold;
1257
+ }
1258
+ return true;
1259
+ }
1260
 
1261
+ /**
1262
+ * Checks that the time taken to swipe meets the minimum / maximum requirements
1263
+ * @return Boolean
1264
+ * @inner
1265
+ */
1266
+ function validateSwipeTime() {
1267
+ var result;
1268
+ //If no time set, then return true
1269
+ if (options.maxTimeThreshold) {
1270
+ if (duration >= options.maxTimeThreshold) {
1271
+ result = false;
1272
+ } else {
1273
+ result = true;
1274
  }
1275
+ } else {
1276
+ result = true;
1277
+ }
1278
 
1279
+ return result;
1280
+ }
 
 
 
 
 
 
 
1281
 
 
 
 
 
 
 
 
 
 
 
1282
 
1283
+ /**
1284
+ * Checks direction of the swipe and the value allowPageScroll to see if we should allow or prevent the default behaviour from occurring.
1285
+ * This will essentially allow page scrolling or not when the user is swiping on a touchSwipe object.
1286
+ * @param {object} jqEvent The normalised jQuery representation of the event object.
1287
+ * @param {string} direction The direction of the event. See {@link $.fn.swipe.directions}
1288
+ * @see $.fn.swipe.directions
1289
+ * @inner
1290
+ */
1291
+ function validateDefaultEvent(jqEvent, direction) {
1292
+
1293
+ //If the option is set, allways allow the event to bubble up (let user handle weirdness)
1294
+ if (options.preventDefaultEvents === false) {
1295
+ return;
1296
+ }
1297
+
1298
+ if (options.allowPageScroll === NONE) {
1299
+ jqEvent.preventDefault();
1300
+ } else {
1301
+ var auto = options.allowPageScroll === AUTO;
1302
+
1303
+ switch (direction) {
1304
+ case LEFT:
1305
+ if ((options.swipeLeft && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1306
+ jqEvent.preventDefault();
1307
+ }
1308
+ break;
1309
 
1310
+ case RIGHT:
1311
+ if ((options.swipeRight && auto) || (!auto && options.allowPageScroll != HORIZONTAL)) {
1312
+ jqEvent.preventDefault();
1313
+ }
1314
+ break;
 
 
 
 
1315
 
1316
+ case UP:
1317
+ if ((options.swipeUp && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1318
+ jqEvent.preventDefault();
 
 
 
 
 
1319
  }
1320
+ break;
 
 
1321
 
1322
+ case DOWN:
1323
+ if ((options.swipeDown && auto) || (!auto && options.allowPageScroll != VERTICAL)) {
1324
+ jqEvent.preventDefault();
1325
+ }
1326
+ break;
 
 
 
1327
 
1328
+ case NONE:
1329
 
1330
+ break;
 
 
 
 
 
 
1331
  }
1332
+ }
1333
+ }
1334
 
 
 
 
 
 
 
 
 
 
1335
 
1336
+ // PINCHES
1337
+ /**
1338
+ * Returns true of the current pinch meets the thresholds
1339
+ * @return Boolean
1340
+ * @inner
1341
+ */
1342
+ function validatePinch() {
1343
+ var hasCorrectFingerCount = validateFingers();
1344
+ var hasEndPoint = validateEndPoint();
1345
+ var hasCorrectDistance = validatePinchDistance();
1346
+ return hasCorrectFingerCount && hasEndPoint && hasCorrectDistance;
1347
 
1348
+ }
1349
 
1350
+ /**
1351
+ * Returns true if any Pinch events have been registered
1352
+ * @return Boolean
1353
+ * @inner
1354
+ */
1355
+ function hasPinches() {
1356
+ //Enure we dont return 0 or null for false values
1357
+ return !!(options.pinchStatus || options.pinchIn || options.pinchOut);
1358
+ }
1359
 
1360
+ /**
1361
+ * Returns true if we are detecting pinches, and have one
1362
+ * @return Boolean
1363
+ * @inner
1364
+ */
1365
+ function didPinch() {
1366
+ //Enure we dont return 0 or null for false values
1367
+ return !!(validatePinch() && hasPinches());
1368
+ }
1369
 
1370
 
1371
 
1372
 
1373
+ // SWIPES
1374
+ /**
1375
+ * Returns true if the current swipe meets the thresholds
1376
+ * @return Boolean
1377
+ * @inner
1378
+ */
1379
+ function validateSwipe() {
1380
+ //Check validity of swipe
1381
+ var hasValidTime = validateSwipeTime();
1382
+ var hasValidDistance = validateSwipeDistance();
1383
+ var hasCorrectFingerCount = validateFingers();
1384
+ var hasEndPoint = validateEndPoint();
1385
+ var didCancel = didSwipeBackToCancel();
1386
+
1387
+ // if the user swiped more than the minimum length, perform the appropriate action
1388
+ // hasValidDistance is null when no distance is set
1389
+ var valid = !didCancel && hasEndPoint && hasCorrectFingerCount && hasValidDistance && hasValidTime;
1390
+
1391
+ return valid;
1392
+ }
1393
 
1394
+ /**
1395
+ * Returns true if any Swipe events have been registered
1396
+ * @return Boolean
1397
+ * @inner
1398
+ */
1399
+ function hasSwipes() {
1400
+ //Enure we dont return 0 or null for false values
1401
+ return !!(options.swipe || options.swipeStatus || options.swipeLeft || options.swipeRight || options.swipeUp || options.swipeDown);
1402
+ }
1403
 
 
 
 
 
 
 
1404
 
1405
+ /**
1406
+ * Returns true if we are detecting swipes and have one
1407
+ * @return Boolean
1408
+ * @inner
1409
+ */
1410
+ function didSwipe() {
1411
+ //Enure we dont return 0 or null for false values
1412
+ return !!(validateSwipe() && hasSwipes());
1413
+ }
1414
 
1415
+ /**
1416
+ * Returns true if we have matched the number of fingers we are looking for
1417
+ * @return Boolean
1418
+ * @inner
1419
+ */
1420
+ function validateFingers() {
1421
+ //The number of fingers we want were matched, or on desktop we ignore
1422
+ return ((fingerCount === options.fingers || options.fingers === ALL_FINGERS) || !SUPPORTS_TOUCH);
1423
+ }
1424
 
1425
+ /**
1426
+ * Returns true if we have an end point for the swipe
1427
+ * @return Boolean
1428
+ * @inner
1429
+ */
1430
+ function validateEndPoint() {
1431
+ //We have an end value for the finger
1432
+ return fingerData[0].end.x !== 0;
1433
+ }
1434
 
1435
+ // TAP / CLICK
1436
+ /**
1437
+ * Returns true if a click / tap events have been registered
1438
+ * @return Boolean
1439
+ * @inner
1440
+ */
1441
+ function hasTap() {
1442
+ //Enure we dont return 0 or null for false values
1443
+ return !!(options.tap);
1444
+ }
1445
 
1446
+ /**
1447
+ * Returns true if a double tap events have been registered
1448
+ * @return Boolean
1449
+ * @inner
1450
+ */
1451
+ function hasDoubleTap() {
1452
+ //Enure we dont return 0 or null for false values
1453
+ return !!(options.doubleTap);
1454
+ }
1455
 
1456
+ /**
1457
+ * Returns true if any long tap events have been registered
1458
+ * @return Boolean
1459
+ * @inner
1460
+ */
1461
+ function hasLongTap() {
1462
+ //Enure we dont return 0 or null for false values
1463
+ return !!(options.longTap);
1464
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1465
 
1466
+ /**
1467
+ * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1468
+ * @return Boolean
1469
+ * @inner
1470
+ */
1471
+ function validateDoubleTap() {
1472
+ if (doubleTapStartTime == null) {
1473
+ return false;
1474
+ }
1475
+ var now = getTimeStamp();
1476
+ return (hasDoubleTap() && ((now - doubleTapStartTime) <= options.doubleTapThreshold));
1477
+ }
1478
 
1479
+ /**
1480
+ * Returns true if we could be in the process of a double tap (one tap has occurred, we are listening for double taps, and the threshold hasn't past.
1481
+ * @return Boolean
1482
+ * @inner
1483
+ */
1484
+ function inDoubleTap() {
1485
+ return validateDoubleTap();
1486
+ }
1487
 
1488
 
1489
+ /**
1490
+ * Returns true if we have a valid tap
1491
+ * @return Boolean
1492
+ * @inner
1493
+ */
1494
+ function validateTap() {
1495
+ return ((fingerCount === 1 || !SUPPORTS_TOUCH) && (isNaN(distance) || distance < options.threshold));
1496
+ }
 
1497
 
1498
+ /**
1499
+ * Returns true if we have a valid long tap
1500
+ * @return Boolean
1501
+ * @inner
1502
+ */
1503
+ function validateLongTap() {
1504
+ //slight threshold on moving finger
1505
+ return ((duration > options.longTapThreshold) && (distance < DOUBLE_TAP_THRESHOLD));
1506
+ }
1507
 
1508
+ /**
1509
+ * Returns true if we are detecting taps and have one
1510
+ * @return Boolean
1511
+ * @inner
1512
+ */
1513
+ function didTap() {
1514
+ //Enure we dont return 0 or null for false values
1515
+ return !!(validateTap() && hasTap());
1516
+ }
1517
 
 
 
 
 
 
 
 
1518
 
1519
+ /**
1520
+ * Returns true if we are detecting double taps and have one
1521
+ * @return Boolean
1522
+ * @inner
1523
+ */
1524
+ function didDoubleTap() {
1525
+ //Enure we dont return 0 or null for false values
1526
+ return !!(validateDoubleTap() && hasDoubleTap());
1527
+ }
1528
 
1529
+ /**
1530
+ * Returns true if we are detecting long taps and have one
1531
+ * @return Boolean
1532
+ * @inner
1533
+ */
1534
+ function didLongTap() {
1535
+ //Enure we dont return 0 or null for false values
1536
+ return !!(validateLongTap() && hasLongTap());
1537
+ }
1538
 
 
 
1539
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1540
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1541
 
1542
+ // MULTI FINGER TOUCH
1543
+ /**
1544
+ * Starts tracking the time between 2 finger releases, and keeps track of how many fingers we initially had up
1545
+ * @inner
1546
+ */
1547
+ function startMultiFingerRelease(event) {
1548
+ previousTouchEndTime = getTimeStamp();
1549
+ fingerCountAtRelease = event.touches.length + 1;
1550
+ }
1551
 
1552
+ /**
1553
+ * Cancels the tracking of time between 2 finger releases, and resets counters
1554
+ * @inner
1555
+ */
1556
+ function cancelMultiFingerRelease() {
1557
+ previousTouchEndTime = 0;
1558
+ fingerCountAtRelease = 0;
1559
+ }
 
 
 
1560
 
1561
+ /**
1562
+ * Checks if we are in the threshold between 2 fingers being released
1563
+ * @return Boolean
1564
+ * @inner
1565
+ */
1566
+ function inMultiFingerRelease() {
 
 
 
 
1567
 
1568
+ var withinThreshold = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
1569
 
1570
+ if (previousTouchEndTime) {
1571
+ var diff = getTimeStamp() - previousTouchEndTime
1572
+ if (diff <= options.fingerReleaseThreshold) {
1573
+ withinThreshold = true;
 
 
 
 
 
 
 
1574
  }
1575
+ }
1576
 
1577
+ return withinThreshold;
1578
+ }
1579
 
 
 
 
1580
 
1581
+ /**
1582
+ * gets a data flag to indicate that a touch is in progress
1583
+ * @return Boolean
1584
+ * @inner
1585
+ */
1586
+ function getTouchInProgress() {
1587
+ //strict equality to ensure only true and false are returned
1588
+ return !!($element.data(PLUGIN_NS + '_intouch') === true);
1589
+ }
1590
 
1591
+ /**
1592
+ * Sets a data flag to indicate that a touch is in progress
1593
+ * @param {boolean} val The value to set the property to
1594
+ * @inner
1595
+ */
1596
+ function setTouchInProgress(val) {
 
 
 
 
 
 
 
1597
 
1598
+ //If destroy is called in an event handler, we have no el, and we have already cleaned up, so return.
1599
+ if(!$element) { return; }
 
 
 
 
 
 
 
 
 
1600
 
1601
+ //Add or remove event listeners depending on touch status
1602
+ if (val === true) {
1603
+ $element.on(MOVE_EV, touchMove);
1604
+ $element.on(END_EV, touchEnd);
1605
 
1606
+ //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1607
+ if (LEAVE_EV) {
1608
+ $element.on(LEAVE_EV, touchLeave);
 
 
 
 
 
 
 
 
 
 
1609
  }
1610
+ } else {
1611
 
1612
+ $element.off(MOVE_EV, touchMove, false);
1613
+ $element.off(END_EV, touchEnd, false);
1614
 
1615
+ //we only have leave events on desktop, we manually calcuate leave on touch as its not supported in webkit
1616
+ if (LEAVE_EV) {
1617
+ $element.off(LEAVE_EV, touchLeave, false);
 
 
 
 
 
 
1618
  }
1619
+ }
1620
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1621
 
1622
+ //strict equality to ensure only true and false can update the value
1623
+ $element.data(PLUGIN_NS + '_intouch', val === true);
1624
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1625
 
1626
 
1627
+ /**
1628
+ * Creates the finger data for the touch/finger in the event object.
1629
+ * @param {int} id The id to store the finger data under (usually the order the fingers were pressed)
1630
+ * @param {object} evt The event object containing finger data
1631
+ * @return finger data object
1632
+ * @inner
1633
+ */
1634
+ function createFingerData(id, evt) {
1635
+ var f = {
1636
+ start: {
1637
+ x: 0,
1638
+ y: 0
1639
+ },
1640
+ last: {
1641
+ x: 0,
1642
+ y: 0
1643
+ },
1644
+ end: {
1645
+ x: 0,
1646
+ y: 0
1647
  }
1648
+ };
1649
+ f.start.x = f.last.x = f.end.x = evt.pageX || evt.clientX;
1650
+ f.start.y = f.last.y = f.end.y = evt.pageY || evt.clientY;
1651
+ fingerData[id] = f;
1652
+ return f;
1653
+ }
1654
 
1655
+ /**
1656
+ * Updates the finger data for a particular event object
1657
+ * @param {object} evt The event object containing the touch/finger data to upadte
1658
+ * @return a finger data object.
1659
+ * @inner
1660
+ */
1661
+ function updateFingerData(evt) {
1662
+ var id = evt.identifier !== undefined ? evt.identifier : 0;
1663
+ var f = getFingerData(id);
1664
 
1665
+ if (f === null) {
1666
+ f = createFingerData(id, evt);
1667
+ }
1668
 
1669
+ f.last.x = f.end.x;
1670
+ f.last.y = f.end.y;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1671
 
1672
+ f.end.x = evt.pageX || evt.clientX;
1673
+ f.end.y = evt.pageY || evt.clientY;
1674
 
1675
+ return f;
1676
  }
1677
 
 
 
 
1678
  /**
1679
+ * Returns a finger data object by its event ID.
1680
+ * Each touch event has an identifier property, which is used
1681
+ * to track repeat touches
1682
+ * @param {int} id The unique id of the finger in the sequence of touch events.
1683
+ * @return a finger data object.
1684
+ * @inner
 
 
 
 
1685
  */
1686
+ function getFingerData(id) {
1687
+ return fingerData[id] || null;
1688
+ }
1689
 
1690
 
1691
+ /**
1692
+ * Sets the maximum distance swiped in the given direction.
1693
+ * If the new value is lower than the current value, the max value is not changed.
1694
+ * @param {string} direction The direction of the swipe
1695
+ * @param {int} distance The distance of the swipe
1696
+ * @inner
1697
+ */
1698
+ function setMaxDistance(direction, distance) {
1699
+ if(direction==NONE) return;
1700
+ distance = Math.max(distance, getMaxDistance(direction));
1701
+ maximumsMap[direction].distance = distance;
1702
+ }
1703
 
1704
+ /**
1705
+ * gets the maximum distance swiped in the given direction.
1706
+ * @param {string} direction The direction of the swipe
1707
+ * @return int The distance of the swipe
1708
+ * @inner
1709
+ */
1710
+ function getMaxDistance(direction) {
1711
+ if (maximumsMap[direction]) return maximumsMap[direction].distance;
1712
+ return undefined;
1713
+ }
1714
 
1715
  /**
1716
+ * Creats a map of directions to maximum swiped values.
1717
+ * @return Object A dictionary of maximum values, indexed by direction.
1718
+ * @inner
 
 
 
 
 
 
 
1719
  */
1720
+ function createMaximumsData() {
1721
+ var maxData = {};
1722
+ maxData[LEFT] = createMaximumVO(LEFT);
1723
+ maxData[RIGHT] = createMaximumVO(RIGHT);
1724
+ maxData[UP] = createMaximumVO(UP);
1725
+ maxData[DOWN] = createMaximumVO(DOWN);
1726
+
1727
+ return maxData;
1728
+ }
1729
 
1730
  /**
1731
+ * Creates a map maximum swiped values for a given swipe direction
1732
+ * @param {string} The direction that these values will be associated with
1733
+ * @return Object Maximum values
1734
+ * @inner
 
 
 
 
 
 
1735
  */
1736
+ function createMaximumVO(dir) {
1737
+ return {
1738
+ direction: dir,
1739
+ distance: 0
1740
+ }
1741
+ }
1742
+
1743
+
1744
+ //
1745
+ // MATHS / UTILS
1746
+ //
1747
 
1748
  /**
1749
+ * Calculate the duration of the swipe
1750
+ * @return int
1751
+ * @inner
 
 
 
 
 
 
 
1752
  */
1753
+ function calculateDuration() {
1754
+ return endTime - startTime;
1755
+ }
1756
 
1757
  /**
1758
+ * Calculate the distance between 2 touches (pinch)
1759
+ * @param {point} startPoint A point object containing x and y co-ordinates
1760
+ * @param {point} endPoint A point object containing x and y co-ordinates
1761
+ * @return int;
1762
+ * @inner
 
 
 
 
 
1763
  */
1764
+ function calculateTouchesDistance(startPoint, endPoint) {
1765
+ var diffX = Math.abs(startPoint.x - endPoint.x);
1766
+ var diffY = Math.abs(startPoint.y - endPoint.y);
1767
+
1768
+ return Math.round(Math.sqrt(diffX * diffX + diffY * diffY));
1769
+ }
1770
 
1771
  /**
1772
+ * Calculate the zoom factor between the start and end distances
1773
+ * @param {int} startDistance Distance (between 2 fingers) the user started pinching at
1774
+ * @param {int} endDistance Distance (between 2 fingers) the user ended pinching at
1775
+ * @return float The zoom value from 0 to 1.
1776
+ * @inner
 
 
 
 
 
 
 
1777
  */
1778
+ function calculatePinchZoom(startDistance, endDistance) {
1779
+ var percent = (endDistance / startDistance) * 1;
1780
+ return percent.toFixed(2);
1781
+ }
1782
+
1783
 
1784
  /**
1785
+ * Returns the pinch direction, either IN or OUT for the given points
1786
+ * @return string Either {@link $.fn.swipe.directions.IN} or {@link $.fn.swipe.directions.OUT}
1787
+ * @see $.fn.swipe.directions
1788
+ * @inner
 
 
 
 
 
 
 
1789
  */
1790
+ function calculatePinchDirection() {
1791
+ if (pinchZoom < 1) {
1792
+ return OUT;
1793
+ } else {
1794
+ return IN;
1795
+ }
1796
+ }
1797
+
1798
 
1799
  /**
1800
+ * Calculate the length / distance of the swipe
1801
+ * @param {point} startPoint A point object containing x and y co-ordinates
1802
+ * @param {point} endPoint A point object containing x and y co-ordinates
1803
+ * @return int
1804
+ * @inner
 
 
 
 
 
 
1805
  */
1806
+ function calculateDistance(startPoint, endPoint) {
1807
+ return Math.round(Math.sqrt(Math.pow(endPoint.x - startPoint.x, 2) + Math.pow(endPoint.y - startPoint.y, 2)));
1808
+ }
1809
 
1810
  /**
1811
+ * Calculate the angle of the swipe
1812
+ * @param {point} startPoint A point object containing x and y co-ordinates
1813
+ * @param {point} endPoint A point object containing x and y co-ordinates
1814
+ * @return int
1815
+ * @inner
 
 
 
 
 
 
1816
  */
1817
+ function calculateAngle(startPoint, endPoint) {
1818
+ var x = startPoint.x - endPoint.x;
1819
+ var y = endPoint.y - startPoint.y;
1820
+ var r = Math.atan2(y, x); //radians
1821
+ var angle = Math.round(r * 180 / Math.PI); //degrees
1822
+
1823
+ //ensure value is positive
1824
+ if (angle < 0) {
1825
+ angle = 360 - Math.abs(angle);
1826
+ }
1827
+
1828
+ return angle;
1829
+ }
1830
 
1831
  /**
1832
+ * Calculate the direction of the swipe
1833
+ * This will also call calculateAngle to get the latest angle of swipe
1834
+ * @param {point} startPoint A point object containing x and y co-ordinates
1835
+ * @param {point} endPoint A point object containing x and y co-ordinates
1836
+ * @return string Either {@link $.fn.swipe.directions.LEFT} / {@link $.fn.swipe.directions.RIGHT} / {@link $.fn.swipe.directions.DOWN} / {@link $.fn.swipe.directions.UP}
1837
+ * @see $.fn.swipe.directions
1838
+ * @inner
 
 
 
1839
  */
1840
+ function calculateDirection(startPoint, endPoint) {
1841
+
1842
+ if( comparePoints(startPoint, endPoint) ) {
1843
+ return NONE;
1844
+ }
1845
+
1846
+ var angle = calculateAngle(startPoint, endPoint);
1847
+
1848
+ if ((angle <= 45) && (angle >= 0)) {
1849
+ return LEFT;
1850
+ } else if ((angle <= 360) && (angle >= 315)) {
1851
+ return LEFT;
1852
+ } else if ((angle >= 135) && (angle <= 225)) {
1853
+ return RIGHT;
1854
+ } else if ((angle > 45) && (angle < 135)) {
1855
+ return DOWN;
1856
+ } else {
1857
+ return UP;
1858
+ }
1859
+ }
1860
+
1861
 
1862
  /**
1863
+ * Returns a MS time stamp of the current time
1864
+ * @return int
1865
+ * @inner
 
 
 
1866
  */
1867
+ function getTimeStamp() {
1868
+ var now = new Date();
1869
+ return now.getTime();
1870
+ }
1871
+
1872
+
1873
 
1874
  /**
1875
+ * Returns a bounds object with left, right, top and bottom properties for the element specified.
1876
+ * @param {DomNode} The DOM node to get the bounds for.
 
 
 
 
 
 
 
 
1877
  */
1878
+ function getbounds(el) {
1879
+ el = $(el);
1880
+ var offset = el.offset();
1881
+
1882
+ var bounds = {
1883
+ left: offset.left,
1884
+ right: offset.left + el.outerWidth(),
1885
+ top: offset.top,
1886
+ bottom: offset.top + el.outerHeight()
1887
+ }
1888
+
1889
+ return bounds;
1890
+ }
1891
+
1892
 
1893
  /**
1894
+ * Checks if the point object is in the bounds object.
1895
+ * @param {object} point A point object.
1896
+ * @param {int} point.x The x value of the point.
1897
+ * @param {int} point.y The x value of the point.
1898
+ * @param {object} bounds The bounds object to test
1899
+ * @param {int} bounds.left The leftmost value
1900
+ * @param {int} bounds.right The righttmost value
1901
+ * @param {int} bounds.top The topmost value
1902
+ * @param {int} bounds.bottom The bottommost value
1903
  */
1904
+ function isInBounds(point, bounds) {
1905
+ return (point.x > bounds.left && point.x < bounds.right && point.y > bounds.top && point.y < bounds.bottom);
1906
+ };
1907
 
1908
  /**
1909
+ * Checks if the two points are equal
1910
+ * @param {object} point A point object.
1911
+ * @param {object} point B point object.
1912
+ * @return true of the points match
 
 
 
 
1913
  */
1914
+ function comparePoints(pointA, pointB) {
1915
+ return (pointA.x == pointB.x && pointA.y == pointB.y);
1916
+ }
1917
+
1918
 
1919
+ }
1920
+
1921
+
1922
+
1923
+
1924
+ /**
1925
+ * A catch all handler that is triggered for all swipe directions.
1926
+ * @name $.fn.swipe#swipe
1927
+ * @event
1928
+ * @default null
1929
+ * @param {EventObject} event The original event object
1930
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1931
+ * @param {int} distance The distance the user swiped
1932
+ * @param {int} duration The duration of the swipe in milliseconds
1933
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1934
+ * @param {object} fingerData The coordinates of fingers in event
1935
+ * @param {string} currentDirection The current direction the user is swiping.
1936
+ */
1937
+
1938
+
1939
+
1940
+
1941
+ /**
1942
+ * A handler that is triggered for "left" swipes.
1943
+ * @name $.fn.swipe#swipeLeft
1944
+ * @event
1945
+ * @default null
1946
+ * @param {EventObject} event The original event object
1947
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1948
+ * @param {int} distance The distance the user swiped
1949
+ * @param {int} duration The duration of the swipe in milliseconds
1950
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1951
+ * @param {object} fingerData The coordinates of fingers in event
1952
+ * @param {string} currentDirection The current direction the user is swiping.
1953
+ */
1954
+
1955
+ /**
1956
+ * A handler that is triggered for "right" swipes.
1957
+ * @name $.fn.swipe#swipeRight
1958
+ * @event
1959
+ * @default null
1960
+ * @param {EventObject} event The original event object
1961
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1962
+ * @param {int} distance The distance the user swiped
1963
+ * @param {int} duration The duration of the swipe in milliseconds
1964
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1965
+ * @param {object} fingerData The coordinates of fingers in event
1966
+ * @param {string} currentDirection The current direction the user is swiping.
1967
+ */
1968
+
1969
+ /**
1970
+ * A handler that is triggered for "up" swipes.
1971
+ * @name $.fn.swipe#swipeUp
1972
+ * @event
1973
+ * @default null
1974
+ * @param {EventObject} event The original event object
1975
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1976
+ * @param {int} distance The distance the user swiped
1977
+ * @param {int} duration The duration of the swipe in milliseconds
1978
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1979
+ * @param {object} fingerData The coordinates of fingers in event
1980
+ * @param {string} currentDirection The current direction the user is swiping.
1981
+ */
1982
+
1983
+ /**
1984
+ * A handler that is triggered for "down" swipes.
1985
+ * @name $.fn.swipe#swipeDown
1986
+ * @event
1987
+ * @default null
1988
+ * @param {EventObject} event The original event object
1989
+ * @param {int} direction The direction the user swiped in. See {@link $.fn.swipe.directions}
1990
+ * @param {int} distance The distance the user swiped
1991
+ * @param {int} duration The duration of the swipe in milliseconds
1992
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
1993
+ * @param {object} fingerData The coordinates of fingers in event
1994
+ * @param {string} currentDirection The current direction the user is swiping.
1995
+ */
1996
+
1997
+ /**
1998
+ * A handler triggered for every phase of the swipe. This handler is constantly fired for the duration of the pinch.
1999
+ * This is triggered regardless of swipe thresholds.
2000
+ * @name $.fn.swipe#swipeStatus
2001
+ * @event
2002
+ * @default null
2003
+ * @param {EventObject} event The original event object
2004
+ * @param {string} phase The phase of the swipe event. See {@link $.fn.swipe.phases}
2005
+ * @param {string} direction The direction the user swiped in. This is null if the user has yet to move. See {@link $.fn.swipe.directions}
2006
+ * @param {int} distance The distance the user swiped. This is 0 if the user has yet to move.
2007
+ * @param {int} duration The duration of the swipe in milliseconds
2008
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2009
+ * @param {object} fingerData The coordinates of fingers in event
2010
+ * @param {string} currentDirection The current direction the user is swiping.
2011
+ */
2012
+
2013
+ /**
2014
+ * A handler triggered for pinch in events.
2015
+ * @name $.fn.swipe#pinchIn
2016
+ * @event
2017
+ * @default null
2018
+ * @param {EventObject} event The original event object
2019
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2020
+ * @param {int} distance The distance the user pinched
2021
+ * @param {int} duration The duration of the swipe in milliseconds
2022
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2023
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2024
+ * @param {object} fingerData The coordinates of fingers in event
2025
+ */
2026
+
2027
+ /**
2028
+ * A handler triggered for pinch out events.
2029
+ * @name $.fn.swipe#pinchOut
2030
+ * @event
2031
+ * @default null
2032
+ * @param {EventObject} event The original event object
2033
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2034
+ * @param {int} distance The distance the user pinched
2035
+ * @param {int} duration The duration of the swipe in milliseconds
2036
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2037
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2038
+ * @param {object} fingerData The coordinates of fingers in event
2039
+ */
2040
+
2041
+ /**
2042
+ * A handler triggered for all pinch events. This handler is constantly fired for the duration of the pinch. This is triggered regardless of thresholds.
2043
+ * @name $.fn.swipe#pinchStatus
2044
+ * @event
2045
+ * @default null
2046
+ * @param {EventObject} event The original event object
2047
+ * @param {int} direction The direction the user pinched in. See {@link $.fn.swipe.directions}
2048
+ * @param {int} distance The distance the user pinched
2049
+ * @param {int} duration The duration of the swipe in milliseconds
2050
+ * @param {int} fingerCount The number of fingers used. See {@link $.fn.swipe.fingers}
2051
+ * @param {int} zoom The zoom/scale level the user pinched too, 0-1.
2052
+ * @param {object} fingerData The coordinates of fingers in event
2053
+ */
2054
+
2055
+ /**
2056
+ * A click handler triggered when a user simply clicks, rather than swipes on an element.
2057
+ * This is deprecated since version 1.6.2, any assignment to click will be assigned to the tap handler.
2058
+ * You cannot use <code>on</code> to bind to this event as the default jQ <code>click</code> event will be triggered.
2059
+ * Use the <code>tap</code> event instead.
2060
+ * @name $.fn.swipe#click
2061
+ * @event
2062
+ * @deprecated since version 1.6.2, please use {@link $.fn.swipe#tap} instead
2063
+ * @default null
2064
+ * @param {EventObject} event The original event object
2065
+ * @param {DomObject} target The element clicked on.
2066
+ */
2067
+
2068
+ /**
2069
+ * A click / tap handler triggered when a user simply clicks or taps, rather than swipes on an element.
2070
+ * @name $.fn.swipe#tap
2071
+ * @event
2072
+ * @default null
2073
+ * @param {EventObject} event The original event object
2074
+ * @param {DomObject} target The element clicked on.
2075
+ */
2076
+
2077
+ /**
2078
+ * A double tap handler triggered when a user double clicks or taps on an element.
2079
+ * You can set the time delay for a double tap with the {@link $.fn.swipe.defaults#doubleTapThreshold} property.
2080
+ * Note: If you set both <code>doubleTap</code> and <code>tap</code> handlers, the <code>tap</code> event will be delayed by the <code>doubleTapThreshold</code>
2081
+ * as the script needs to check if its a double tap.
2082
+ * @name $.fn.swipe#doubleTap
2083
+ * @see $.fn.swipe.defaults#doubleTapThreshold
2084
+ * @event
2085
+ * @default null
2086
+ * @param {EventObject} event The original event object
2087
+ * @param {DomObject} target The element clicked on.
2088
+ */
2089
+
2090
+ /**
2091
+ * A long tap handler triggered once a tap has been release if the tap was longer than the longTapThreshold.
2092
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2093
+ * @name $.fn.swipe#longTap
2094
+ * @see $.fn.swipe.defaults#longTapThreshold
2095
+ * @event
2096
+ * @default null
2097
+ * @param {EventObject} event The original event object
2098
+ * @param {DomObject} target The element clicked on.
2099
+ */
2100
+
2101
+ /**
2102
+ * A hold tap handler triggered as soon as the longTapThreshold is reached
2103
+ * You can set the time delay for a long tap with the {@link $.fn.swipe.defaults#longTapThreshold} property.
2104
+ * @name $.fn.swipe#hold
2105
+ * @see $.fn.swipe.defaults#longTapThreshold
2106
+ * @event
2107
+ * @default null
2108
+ * @param {EventObject} event The original event object
2109
+ * @param {DomObject} target The element clicked on.
2110
+ */
2111
+
2112
+ }));
js/jquery.touchSwipe.min.js CHANGED
@@ -1 +1,14 @@
1
- !function(e){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery.touchSwipe.js"],e):e(jQuery)}((function(e){"use strict";var n="left",t="up",i="ontouchstart"in window,r=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled,l=window.navigator.pointerEnabled||window.navigator.msPointerEnabled;function o(n){return!n||void 0!==n.allowPageScroll||void 0===n.swipe&&void 0===n.swipeStatus||(n.allowPageScroll="none"),void 0!==n.click&&void 0===n.tap&&(n.tap=n.click),n||(n={}),n=e.extend({},e.fn.swipe.defaults,n),this.each((function(){var t=e(this),i=t.data("TouchSwipe");i||(i=new a(this,n),t.data("TouchSwipe",i))}))}function a(o,a){var u=i||l||!a.fallbackToMouseEvents,c=u?l?r?"MSPointerDown":"pointerdown":"touchstart":"mousedown",s=u?l?r?"MSPointerMove":"pointermove":"touchmove":"mousemove",h=u?l?r?"MSPointerUp":"pointerup":"touchend":"mouseup",p=u?null:"mouseleave",d=l?r?"MSPointerCancel":"pointercancel":"touchcancel",f=0,g=null,w=0,v=0,T=0,b=1,S=0,m=0,E=null,y=e(o),O="start",x=0,M=null,P=0,D=0,L=0,R=0,k=0,A=null,I=null;try{y.bind(c,N),y.bind(d,H)}catch(n){e.error("events not supported "+c+","+d+" on jQuery.swipe")}function N(r){if(!0!==y.data("TouchSwipe_intouch")&&!(e(r.target).closest(a.excludedElements,y).length>0)){var l,o,u=r.originalEvent?r.originalEvent:r,c=i?u.touches[0]:u;return O="start",i?x=u.touches.length:r.preventDefault(),f=0,g=null,m=null,w=0,v=0,T=0,b=1,S=0,M=function(){for(var e=[],n=0;n<=5;n++)e.push({start:{x:0,y:0},end:{x:0,y:0},identifier:0});return e}(),(o={}).left=se(n),o.right=se("right"),o.up=se(t),o.down=se("down"),E=o,re(),!i||x===a.fingers||"all"===a.fingers||V()?(ae(0,c),P=de(),2==x&&(ae(1,u.touches[1]),v=T=pe(M[0].start,M[1].start)),(a.swipeStatus||a.pinchStatus)&&(l=X(u,O))):l=!1,!1===l?(X(u,O="cancel"),l):(a.hold&&(I=setTimeout(e.proxy((function(){y.trigger("hold",[u.target]),a.hold&&(l=a.hold.call(y,u,u.target))}),this),a.longTapThreshold)),oe(!0),null)}}function U(r){var l=r.originalEvent?r.originalEvent:r;if("end"!==O&&"cancel"!==O&&!le()){var o,u,c,s,h,p,d=ue(i?l.touches[0]:l);if(D=de(),i&&(x=l.touches.length),a.hold&&clearTimeout(I),O="move",2==x&&(0==v?(ae(1,l.touches[1]),v=T=pe(M[0].start,M[1].start)):(ue(l.touches[1]),T=pe(M[0].end,M[1].end),M[0].end,M[1].end,m=b<1?"out":"in"),b=(T/v*1).toFixed(2),S=Math.abs(v-T)),x===a.fingers||"all"===a.fingers||!i||V()){if(s=d.start,h=d.end,p=function(e,n){var t=e.x-n.x,i=n.y-e.y,r=Math.atan2(i,t),l=Math.round(180*r/Math.PI);return l<0&&(l=360-Math.abs(l)),l}(s,h),function(e,i){if(!1===a.preventDefaultEvents)return;if("none"===a.allowPageScroll)e.preventDefault();else{var r="auto"===a.allowPageScroll;switch(i){case n:(a.swipeLeft&&r||!r&&"horizontal"!=a.allowPageScroll)&&e.preventDefault();break;case"right":(a.swipeRight&&r||!r&&"horizontal"!=a.allowPageScroll)&&e.preventDefault();break;case t:(a.swipeUp&&r||!r&&"vertical"!=a.allowPageScroll)&&e.preventDefault();break;case"down":(a.swipeDown&&r||!r&&"vertical"!=a.allowPageScroll)&&e.preventDefault()}}}(r,g=p<=45&&p>=0?n:p<=360&&p>=315?n:p>=135&&p<=225?"right":p>45&&p<135?"down":t),f=function(e,n){return Math.round(Math.sqrt(Math.pow(n.x-e.x,2)+Math.pow(n.y-e.y,2)))}(d.start,d.end),w=he(),function(e,n){n=Math.max(n,ce(e)),E[e].distance=n}(g,f),(a.swipeStatus||a.pinchStatus)&&(o=X(l,O)),!a.triggerOnTouchEnd||a.triggerOnTouchLeave){var y=!0;if(a.triggerOnTouchLeave){var P={left:(c=(u=e(u=this)).offset()).left,right:c.left+u.outerWidth(),top:c.top,bottom:c.top+u.outerHeight()};y=function(e,n){return e.x>n.left&&e.x<n.right&&e.y>n.top&&e.y<n.bottom}(d.end,P)}!a.triggerOnTouchEnd&&y?O=C("move"):a.triggerOnTouchLeave&&!y&&(O=C("end")),"cancel"!=O&&"end"!=O||X(l,O)}}else X(l,O="cancel");!1===o&&X(l,O="cancel")}}function j(e){var n=e.originalEvent;return i&&n.touches.length>0?(ie(),!0):(le()&&(x=R),D=de(),w=he(),z()||!q()?X(n,O="cancel"):a.triggerOnTouchEnd||0==a.triggerOnTouchEnd&&"move"===O?(e.preventDefault(),X(n,O="end")):!a.triggerOnTouchEnd&&ee()?Y(n,O="end","tap"):"move"===O&&X(n,O="cancel"),oe(!1),null)}function H(){x=0,D=0,P=0,v=0,T=0,b=1,re(),oe(!1)}function _(e){var n=e.originalEvent;a.triggerOnTouchLeave&&X(n,O=C("end"))}function Q(){y.unbind(c,N),y.unbind(d,H),y.unbind(s,U),y.unbind(h,j),p&&y.unbind(p,_),oe(!1)}function C(e){var n=e,t=W(),i=q(),r=z();return!t||r?n="cancel":!i||"move"!=e||a.triggerOnTouchEnd&&!a.triggerOnTouchLeave?!i&&"end"==e&&a.triggerOnTouchLeave&&(n="cancel"):n="end",n}function X(e,n){var t=void 0;return J()||B()||G()||V()?((J()||B())&&(t=Y(e,n,"swipe")),(G()||V())&&!1!==t&&(t=Y(e,n,"pinch"))):te()&&ne()&&!1!==t?t=Y(e,n,"doubletap"):w>a.longTapThreshold&&f<10&&a.longTap&&!1!==t?t=Y(e,n,"longtap"):1!==x&&i||!(isNaN(f)||f<a.threshold)||!ee()||!1===t||(t=Y(e,n,"tap")),"cancel"===n&&H(),"end"===n&&(i?0==e.touches.length&&H():H()),t}function Y(i,r,l){var o=void 0;if("swipe"==l){if(y.trigger("swipeStatus",[r,g||null,f||0,w||0,x,M]),a.swipeStatus&&!1===(o=a.swipeStatus.call(y,i,r,g||null,f||0,w||0,x,M)))return!1;if("end"==r&&Z()){if(y.trigger("swipe",[g,f,w,x,M]),a.swipe&&!1===(o=a.swipe.call(y,i,g,f,w,x,M)))return!1;switch(g){case n:y.trigger("swipeLeft",[g,f,w,x,M]),a.swipeLeft&&(o=a.swipeLeft.call(y,i,g,f,w,x,M));break;case"right":y.trigger("swipeRight",[g,f,w,x,M]),a.swipeRight&&(o=a.swipeRight.call(y,i,g,f,w,x,M));break;case t:y.trigger("swipeUp",[g,f,w,x,M]),a.swipeUp&&(o=a.swipeUp.call(y,i,g,f,w,x,M));break;case"down":y.trigger("swipeDown",[g,f,w,x,M]),a.swipeDown&&(o=a.swipeDown.call(y,i,g,f,w,x,M))}}}if("pinch"==l){if(y.trigger("pinchStatus",[r,m||null,S||0,w||0,x,b,M]),a.pinchStatus&&!1===(o=a.pinchStatus.call(y,i,r,m||null,S||0,w||0,x,b,M)))return!1;if("end"==r&&F())switch(m){case"in":y.trigger("pinchIn",[m||null,S||0,w||0,x,b,M]),a.pinchIn&&(o=a.pinchIn.call(y,i,m||null,S||0,w||0,x,b,M));break;case"out":y.trigger("pinchOut",[m||null,S||0,w||0,x,b,M]),a.pinchOut&&(o=a.pinchOut.call(y,i,m||null,S||0,w||0,x,b,M))}}return"tap"==l?"cancel"!==r&&"end"!==r||(clearTimeout(A),clearTimeout(I),ne()&&!te()?(k=de(),A=setTimeout(e.proxy((function(){k=null,y.trigger("tap",[i.target]),a.tap&&(o=a.tap.call(y,i,i.target))}),this),a.doubleTapThreshold)):(k=null,y.trigger("tap",[i.target]),a.tap&&(o=a.tap.call(y,i,i.target)))):"doubletap"==l?"cancel"!==r&&"end"!==r||(clearTimeout(A),k=null,y.trigger("doubletap",[i.target]),a.doubleTap&&(o=a.doubleTap.call(y,i,i.target))):"longtap"==l&&("cancel"!==r&&"end"!==r||(clearTimeout(A),k=null,y.trigger("longtap",[i.target]),a.longTap&&(o=a.longTap.call(y,i,i.target)))),o}function q(){var e=!0;return null!==a.threshold&&(e=f>=a.threshold),e}function z(){var e=!1;return null!==a.cancelThreshold&&null!==g&&(e=ce(g)-f>=a.cancelThreshold),e}function W(){return!a.maxTimeThreshold||!(w>=a.maxTimeThreshold)}function F(){var e=K(),n=$(),t=null===a.pinchThreshold||S>=a.pinchThreshold;return e&&n&&t}function V(){return!!(a.pinchStatus||a.pinchIn||a.pinchOut)}function G(){return!(!F()||!V())}function Z(){var e=W(),n=q(),t=K(),i=$();return!z()&&i&&t&&n&&e}function B(){return!!(a.swipe||a.swipeStatus||a.swipeLeft||a.swipeRight||a.swipeUp||a.swipeDown)}function J(){return!(!Z()||!B())}function K(){return x===a.fingers||"all"===a.fingers||!i}function $(){return 0!==M[0].end.x}function ee(){return!!a.tap}function ne(){return!!a.doubleTap}function te(){if(null==k)return!1;var e=de();return ne()&&e-k<=a.doubleTapThreshold}function ie(){L=de(),R=event.touches.length+1}function re(){L=0,R=0}function le(){var e=!1;L&&(de()-L<=a.fingerReleaseThreshold&&(e=!0));return e}function oe(e){!0===e?(y.bind(s,U),y.bind(h,j),p&&y.bind(p,_)):(y.unbind(s,U,!1),y.unbind(h,j,!1),p&&y.unbind(p,_,!1)),y.data("TouchSwipe_intouch",!0===e)}function ae(e,n){var t=void 0!==n.identifier?n.identifier:0;return M[e].identifier=t,M[e].start.x=M[e].end.x=n.pageX||n.clientX,M[e].start.y=M[e].end.y=n.pageY||n.clientY,M[e]}function ue(e){var n=function(e){for(var n=0;n<M.length;n++)if(M[n].identifier==e)return M[n]}(void 0!==e.identifier?e.identifier:0);return n.end.x=e.pageX||e.clientX,n.end.y=e.pageY||e.clientY,n}function ce(e){if(E[e])return E[e].distance}function se(e){return{direction:e,distance:0}}function he(){return D-P}function pe(e,n){var t=Math.abs(e.x-n.x),i=Math.abs(e.y-n.y);return Math.round(Math.sqrt(t*t+i*i))}function de(){return(new Date).getTime()}this.enable=function(){return y.bind(c,N),y.bind(d,H),y},this.disable=function(){return Q(),y},this.destroy=function(){Q(),y.data("TouchSwipe",null),y=null},this.option=function(n,t){if(void 0!==a[n]){if(void 0===t)return a[n];a[n]=t}else e.error("Option "+n+" does not exist on jQuery.swipe.options");return null}}e.fn.swipe=function(n){var t=e(this),i=t.data("TouchSwipe");if(i&&"string"==typeof n){if(i[n])return i[n].apply(this,Array.prototype.slice.call(arguments,1));e.error("Method "+n+" does not exist on jQuery.swipe")}else if(!(i||"object"!=typeof n&&n))return o.apply(this,arguments);return t},e.fn.swipe.defaults={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,hold:null,triggerOnTouchEnd:!0,triggerOnTouchLeave:!1,allowPageScroll:"auto",fallbackToMouseEvents:!0,excludedElements:"label, button, input, select, textarea, a, .noSwipe",preventDefaultEvents:!0},e.fn.swipe.phases={PHASE_START:"start",PHASE_MOVE:"move",PHASE_END:"end",PHASE_CANCEL:"cancel"},e.fn.swipe.directions={LEFT:n,RIGHT:"right",UP:t,DOWN:"down",IN:"in",OUT:"out"},e.fn.swipe.pageScroll={NONE:"none",HORIZONTAL:"horizontal",VERTICAL:"vertical",AUTO:"auto"},e.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:"all"}}));
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * @fileOverview TouchSwipe - jQuery Plugin
3
+ * @version 1.6.18
4
+ *
5
+ * @author Matt Bryson http://www.github.com/mattbryson
6
+ * @see https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
7
+ * @see http://labs.rampinteractive.co.uk/touchSwipe/
8
+ * @see http://plugins.jquery.com/project/touchSwipe
9
+ * @license
10
+ * Copyright (c) 2010-2015 Matt Bryson
11
+ * Dual licensed under the MIT or GPL Version 2 licenses.
12
+ *
13
+ */
14
+ !function(e){"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],e):"undefined"!=typeof module&&module.exports?e(require("jquery")):e(jQuery)}((function(e){"use strict";var n="left",t="up",r="ontouchstart"in window,i=window.navigator.msPointerEnabled&&!window.PointerEvent&&!r,l=(window.PointerEvent||window.navigator.msPointerEnabled)&&!r;function o(n){return!n||void 0!==n.allowPageScroll||void 0===n.swipe&&void 0===n.swipeStatus||(n.allowPageScroll="none"),void 0!==n.click&&void 0===n.tap&&(n.tap=n.click),n||(n={}),n=e.extend({},e.fn.swipe.defaults,n),this.each((function(){var t=e(this),r=t.data("TouchSwipe");r||(r=new a(this,n),t.data("TouchSwipe",r))}))}function a(o,a){a=e.extend({},a);var u=r||l||!a.fallbackToMouseEvents,c=u?l?i?"MSPointerDown":"pointerdown":"touchstart":"mousedown",s=u?l?i?"MSPointerMove":"pointermove":"touchmove":"mousemove",p=u?l?i?"MSPointerUp":"pointerup":"touchend":"mouseup",h=u?l?"mouseleave":null:"mouseleave",f=l?i?"MSPointerCancel":"pointercancel":"touchcancel",d=0,g=null,w=null,v=0,T=0,m=0,y=1,E=0,S=0,b=null,x=e(o),O="start",M=0,P={},D=0,L=0,R=0,k=0,A=0,I=null,U=null;try{x.on(c,j),x.on(f,_)}catch(n){e.error("events not supported "+c+","+f+" on jQuery.swipe")}function j(r){if(!0!==x.data("TouchSwipe_intouch")&&!(e(r.target).closest(a.excludedElements,x).length>0)){var i=r.originalEvent?r.originalEvent:r;if(!i.pointerType||"mouse"!=i.pointerType||0!=a.fallbackToMouseEvents){var l,o,u=i.touches,c=u?u[0]:i;return O="start",u?M=u.length:!1!==a.preventDefaultEvents&&r.preventDefault(),d=0,g=null,w=null,S=null,v=0,T=0,m=0,y=1,E=0,(o={}).left=ue(n),o.right=ue("right"),o.up=ue(t),o.down=ue("down"),b=o,te(),le(0,c),!u||M===a.fingers||"all"===a.fingers||G()?(D=he(),2==M&&(le(1,u[1]),T=m=se(P[0].start,P[1].start)),(a.swipeStatus||a.pinchStatus)&&(l=F(i,O))):l=!1,!1===l?(F(i,O="cancel"),l):(a.hold&&(U=setTimeout(e.proxy((function(){x.trigger("hold",[i.target]),a.hold&&(l=a.hold.call(x,i,i.target))}),this),a.longTapThreshold)),ie(!0),null)}}}function N(r){var i=r.originalEvent?r.originalEvent:r;if("end"!==O&&"cancel"!==O&&!re()){var l,o,u,c,s,p=i.touches,h=oe(p?p[0]:i);if(L=he(),p&&(M=p.length),a.hold&&clearTimeout(U),O="move",2==M&&(0==T?(le(1,p[1]),T=m=se(P[0].start,P[1].start)):(oe(p[1]),m=se(P[0].end,P[1].end),P[0].end,P[1].end,S=y<1?"out":"in"),y=(m/T*1).toFixed(2),E=Math.abs(T-m)),M===a.fingers||"all"===a.fingers||!p||G()){if(g=pe(h.start,h.end),function(e,r){if(!1===a.preventDefaultEvents)return;if("none"===a.allowPageScroll)e.preventDefault();else{var i="auto"===a.allowPageScroll;switch(r){case n:(a.swipeLeft&&i||!i&&"horizontal"!=a.allowPageScroll)&&e.preventDefault();break;case"right":(a.swipeRight&&i||!i&&"horizontal"!=a.allowPageScroll)&&e.preventDefault();break;case t:(a.swipeUp&&i||!i&&"vertical"!=a.allowPageScroll)&&e.preventDefault();break;case"down":(a.swipeDown&&i||!i&&"vertical"!=a.allowPageScroll)&&e.preventDefault()}}}(r,w=pe(h.last,h.end)),c=h.start,s=h.end,d=Math.round(Math.sqrt(Math.pow(s.x-c.x,2)+Math.pow(s.y-c.y,2))),v=ce(),function(e,n){if("none"==e)return;n=Math.max(n,ae(e)),b[e].distance=n}(g,d),l=F(i,O),!a.triggerOnTouchEnd||a.triggerOnTouchLeave){var f=!0;if(a.triggerOnTouchLeave){var x={left:(u=(o=e(o=this)).offset()).left,right:u.left+o.outerWidth(),top:u.top,bottom:u.top+o.outerHeight()};f=function(e,n){return e.x>n.left&&e.x<n.right&&e.y>n.top&&e.y<n.bottom}(h.end,x)}!a.triggerOnTouchEnd&&f?O=C("move"):a.triggerOnTouchLeave&&!f&&(O=C("end")),"cancel"!=O&&"end"!=O||F(i,O)}}else F(i,O="cancel");!1===l&&F(i,O="cancel")}}function H(e){var n=e.originalEvent?e.originalEvent:e,t=n.touches;if(t){if(t.length&&!re())return function(e){R=he(),k=e.touches.length+1}(n),!0;if(t.length&&re())return!0}return re()&&(M=k),L=he(),v=ce(),z()||!Y()?F(n,O="cancel"):a.triggerOnTouchEnd||!1===a.triggerOnTouchEnd&&"move"===O?(!1!==a.preventDefaultEvents&&!1!==e.cancelable&&e.preventDefault(),F(n,O="end")):!a.triggerOnTouchEnd&&$()?X(n,O="end","tap"):"move"===O&&F(n,O="cancel"),ie(!1),null}function _(){M=0,L=0,D=0,T=0,m=0,y=1,te(),ie(!1)}function q(e){var n=e.originalEvent?e.originalEvent:e;a.triggerOnTouchLeave&&F(n,O=C("end"))}function Q(){x.off(c,j),x.off(f,_),x.off(s,N),x.off(p,H),h&&x.off(h,q),ie(!1)}function C(e){var n=e,t=V(),r=Y(),i=z();return!t||i?n="cancel":!r||"move"!=e||a.triggerOnTouchEnd&&!a.triggerOnTouchLeave?!r&&"end"==e&&a.triggerOnTouchLeave&&(n="cancel"):n="end",n}function F(e,n){var t,i=e.touches;return(Z()&&B()||B())&&(t=X(e,n,"swipe")),(W()&&G()||G())&&!1!==t&&(t=X(e,n,"pinch")),ne()&&ee()&&!1!==t?t=X(e,n,"doubletap"):v>a.longTapThreshold&&d<10&&a.longTap&&!1!==t?t=X(e,n,"longtap"):1!==M&&r||!(isNaN(d)||d<a.threshold)||!$()||!1===t||(t=X(e,n,"tap")),"cancel"===n&&_(),"end"===n&&(i&&i.length||_()),t}function X(r,i,l){var o;if("swipe"==l){if(x.trigger("swipeStatus",[i,g||null,d||0,v||0,M,P,w]),a.swipeStatus&&!1===(o=a.swipeStatus.call(x,r,i,g||null,d||0,v||0,M,P,w)))return!1;if("end"==i&&Z()){if(clearTimeout(I),clearTimeout(U),x.trigger("swipe",[g,d,v,M,P,w]),a.swipe&&!1===(o=a.swipe.call(x,r,g,d,v,M,P,w)))return!1;switch(g){case n:x.trigger("swipeLeft",[g,d,v,M,P,w]),a.swipeLeft&&(o=a.swipeLeft.call(x,r,g,d,v,M,P,w));break;case"right":x.trigger("swipeRight",[g,d,v,M,P,w]),a.swipeRight&&(o=a.swipeRight.call(x,r,g,d,v,M,P,w));break;case t:x.trigger("swipeUp",[g,d,v,M,P,w]),a.swipeUp&&(o=a.swipeUp.call(x,r,g,d,v,M,P,w));break;case"down":x.trigger("swipeDown",[g,d,v,M,P,w]),a.swipeDown&&(o=a.swipeDown.call(x,r,g,d,v,M,P,w))}}}if("pinch"==l){if(x.trigger("pinchStatus",[i,S||null,E||0,v||0,M,y,P]),a.pinchStatus&&!1===(o=a.pinchStatus.call(x,r,i,S||null,E||0,v||0,M,y,P)))return!1;if("end"==i&&W())switch(S){case"in":x.trigger("pinchIn",[S||null,E||0,v||0,M,y,P]),a.pinchIn&&(o=a.pinchIn.call(x,r,S||null,E||0,v||0,M,y,P));break;case"out":x.trigger("pinchOut",[S||null,E||0,v||0,M,y,P]),a.pinchOut&&(o=a.pinchOut.call(x,r,S||null,E||0,v||0,M,y,P))}}return"tap"==l?"cancel"!==i&&"end"!==i||(clearTimeout(I),clearTimeout(U),ee()&&!ne()?(A=he(),I=setTimeout(e.proxy((function(){A=null,x.trigger("tap",[r.target]),a.tap&&(o=a.tap.call(x,r,r.target))}),this),a.doubleTapThreshold)):(A=null,x.trigger("tap",[r.target]),a.tap&&(o=a.tap.call(x,r,r.target)))):"doubletap"==l?"cancel"!==i&&"end"!==i||(clearTimeout(I),clearTimeout(U),A=null,x.trigger("doubletap",[r.target]),a.doubleTap&&(o=a.doubleTap.call(x,r,r.target))):"longtap"==l&&("cancel"!==i&&"end"!==i||(clearTimeout(I),A=null,x.trigger("longtap",[r.target]),a.longTap&&(o=a.longTap.call(x,r,r.target)))),o}function Y(){var e=!0;return null!==a.threshold&&(e=d>=a.threshold),e}function z(){var e=!1;return null!==a.cancelThreshold&&null!==g&&(e=ae(g)-d>=a.cancelThreshold),e}function V(){return!a.maxTimeThreshold||!(v>=a.maxTimeThreshold)}function W(){var e=J(),n=K(),t=null===a.pinchThreshold||E>=a.pinchThreshold;return e&&n&&t}function G(){return!!(a.pinchStatus||a.pinchIn||a.pinchOut)}function Z(){var e=V(),n=Y(),t=J(),r=K();return!z()&&r&&t&&n&&e}function B(){return!!(a.swipe||a.swipeStatus||a.swipeLeft||a.swipeRight||a.swipeUp||a.swipeDown)}function J(){return M===a.fingers||"all"===a.fingers||!r}function K(){return 0!==P[0].end.x}function $(){return!!a.tap}function ee(){return!!a.doubleTap}function ne(){if(null==A)return!1;var e=he();return ee()&&e-A<=a.doubleTapThreshold}function te(){R=0,k=0}function re(){var e=!1;R&&(he()-R<=a.fingerReleaseThreshold&&(e=!0));return e}function ie(e){x&&(!0===e?(x.on(s,N),x.on(p,H),h&&x.on(h,q)):(x.off(s,N,!1),x.off(p,H,!1),h&&x.off(h,q,!1)),x.data("TouchSwipe_intouch",!0===e))}function le(e,n){var t={start:{x:0,y:0},last:{x:0,y:0},end:{x:0,y:0}};return t.start.x=t.last.x=t.end.x=n.pageX||n.clientX,t.start.y=t.last.y=t.end.y=n.pageY||n.clientY,P[e]=t,t}function oe(e){var n=void 0!==e.identifier?e.identifier:0,t=function(e){return P[e]||null}(n);return null===t&&(t=le(n,e)),t.last.x=t.end.x,t.last.y=t.end.y,t.end.x=e.pageX||e.clientX,t.end.y=e.pageY||e.clientY,t}function ae(e){if(b[e])return b[e].distance}function ue(e){return{direction:e,distance:0}}function ce(){return L-D}function se(e,n){var t=Math.abs(e.x-n.x),r=Math.abs(e.y-n.y);return Math.round(Math.sqrt(t*t+r*r))}function pe(e,r){if(l=r,(i=e).x==l.x&&i.y==l.y)return"none";var i,l,o=function(e,n){var t=e.x-n.x,r=n.y-e.y,i=Math.atan2(r,t),l=Math.round(180*i/Math.PI);return l<0&&(l=360-Math.abs(l)),l}(e,r);return o<=45&&o>=0?n:o<=360&&o>=315?n:o>=135&&o<=225?"right":o>45&&o<135?"down":t}function he(){return(new Date).getTime()}this.enable=function(){return this.disable(),x.on(c,j),x.on(f,_),x},this.disable=function(){return Q(),x},this.destroy=function(){Q(),x.data("TouchSwipe",null),x=null},this.option=function(n,t){if("object"==typeof n)a=e.extend(a,n);else if(void 0!==a[n]){if(void 0===t)return a[n];a[n]=t}else{if(!n)return a;e.error("Option "+n+" does not exist on jQuery.swipe.options")}return null}}e.fn.swipe=function(n){var t=e(this),r=t.data("TouchSwipe");if(r&&"string"==typeof n){if(r[n])return r[n].apply(r,Array.prototype.slice.call(arguments,1));e.error("Method "+n+" does not exist on jQuery.swipe")}else if(r&&"object"==typeof n)r.option.apply(r,arguments);else if(!(r||"object"!=typeof n&&n))return o.apply(this,arguments);return t},e.fn.swipe.version="1.6.18",e.fn.swipe.defaults={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,hold:null,triggerOnTouchEnd:!0,triggerOnTouchLeave:!1,allowPageScroll:"auto",fallbackToMouseEvents:!0,excludedElements:".noSwipe",preventDefaultEvents:!0},e.fn.swipe.phases={PHASE_START:"start",PHASE_MOVE:"move",PHASE_END:"end",PHASE_CANCEL:"cancel"},e.fn.swipe.directions={LEFT:n,RIGHT:"right",UP:t,DOWN:"down",IN:"in",OUT:"out"},e.fn.swipe.pageScroll={NONE:"none",HORIZONTAL:"horizontal",VERTICAL:"vertical",AUTO:"auto"},e.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,FOUR:4,FIVE:5,ALL:"all"}}));
lang/so-widgets-bundle.pot CHANGED
@@ -125,11 +125,11 @@ msgid "Visual Composer"
125
  msgstr ""
126
 
127
  #: icons/icons.php:7
128
- msgid "Elegant Themes Line Icons"
129
  msgstr ""
130
 
131
  #: icons/icons.php:8
132
- msgid "Font Awesome"
133
  msgstr ""
134
 
135
  #: icons/icons.php:9
@@ -265,18 +265,18 @@ msgid "Allows you to add any active SiteOrigin Widgets Bundle widgets."
265
  msgstr ""
266
 
267
  #: icons/fontawesome/filter.php:1376
268
- msgid "Brands"
269
- msgstr ""
270
-
271
- #: icons/fontawesome/filter.php:1377
272
  msgid "Regular"
273
  msgstr ""
274
 
275
- #: icons/fontawesome/filter.php:1378, widgets/contact/contact.php:363, widgets/contact/contact.php:480, widgets/contact/contact.php:588, widgets/contact/contact.php:666, widgets/headline/headline.php:189
276
  msgid "Solid"
277
  msgstr ""
278
 
279
- #: widgets/accordion/accordion.php:4
 
 
 
 
280
  msgid "An accordion to squeeze a lot of content into a small space."
281
  msgstr ""
282
 
@@ -284,11 +284,7 @@ msgstr ""
284
  msgid "SiteOrigin Accordion"
285
  msgstr ""
286
 
287
- #: widgets/accordion/accordion.php:17
288
- msgid "An accordion widget."
289
- msgstr ""
290
-
291
- #: widgets/accordion/accordion.php:47, widgets/accordion/accordion.php:60, widgets/contact/contact.php:48, widgets/cta/cta.php:64, widgets/editor/editor.php:33, widgets/features/features.php:136, widgets/post-carousel/post-carousel.php:98, widgets/price-table/price-table.php:42, widgets/price-table/price-table.php:61, widgets/simple-masonry/simple-masonry.php:44, widgets/simple-masonry/simple-masonry.php:75, widgets/social-media-buttons/social-media-buttons.php:54, widgets/tabs/tabs.php:47, widgets/tabs/tabs.php:60, widgets/taxonomy/taxonomy.php:34, widgets/testimonial/testimonial.php:41, widgets/video/video.php:33, base/inc/fields/posts.class.php:97
292
  msgid "Title"
293
  msgstr ""
294
 
@@ -296,7 +292,7 @@ msgstr ""
296
  msgid "Panels"
297
  msgstr ""
298
 
299
- #: widgets/accordion/accordion.php:64, widgets/hero/hero.php:62, widgets/layout-slider/layout-slider.php:49, widgets/tabs/tabs.php:64
300
  msgid "Content"
301
  msgstr ""
302
 
@@ -324,7 +320,7 @@ msgstr ""
324
  msgid "Headings"
325
  msgstr ""
326
 
327
- #: widgets/accordion/accordion.php:90, widgets/accordion/accordion.php:128, widgets/contact/contact.php:336, widgets/contact/contact.php:569, widgets/cta/cta.php:78, widgets/hero/hero.php:122, widgets/layout-slider/layout-slider.php:83, widgets/social-media-buttons/social-media-buttons.php:86, widgets/tabs/tabs.php:86, widgets/tabs/tabs.php:106, widgets/tabs/tabs.php:150
328
  msgid "Background color"
329
  msgstr ""
330
 
@@ -364,7 +360,7 @@ msgstr ""
364
  msgid "Get more customization options and the ability to use widgets and layouts as your accordion content with %sSiteOrigin Premium%s"
365
  msgstr ""
366
 
367
- #: widgets/button/button.php:4
368
  msgid "A powerful yet simple button widget for your sidebars or Page Builder pages."
369
  msgstr ""
370
 
@@ -372,19 +368,15 @@ msgstr ""
372
  msgid "SiteOrigin Button"
373
  msgstr ""
374
 
375
- #: widgets/button/button.php:17
376
- msgid "A customizable button widget."
377
- msgstr ""
378
-
379
  #: widgets/button/button.php:46, widgets/price-table/price-table.php:93
380
  msgid "Button text"
381
  msgstr ""
382
 
383
- #: widgets/button/button.php:51, widgets/google-map/google-map.php:103, widgets/headline/headline.php:47, widgets/headline/headline.php:118, widgets/hero/hero.php:128, widgets/icon/icon.php:57, widgets/image/image.php:89, widgets/layout-slider/layout-slider.php:89, widgets/simple-masonry/simple-masonry.php:79, widgets/slider/slider.php:85
384
  msgid "Destination URL"
385
  msgstr ""
386
 
387
- #: widgets/button/button.php:57, widgets/google-map/google-map.php:114, widgets/headline/headline.php:52, widgets/headline/headline.php:123, widgets/icon/icon.php:63, widgets/simple-masonry/simple-masonry.php:84, widgets/social-media-buttons/social-media-buttons.php:97, widgets/taxonomy/taxonomy.php:65, widgets/testimonial/testimonial.php:94
388
  msgid "Open in a new window"
389
  msgstr ""
390
 
@@ -468,7 +460,7 @@ msgstr ""
468
  msgid "Button color"
469
  msgstr ""
470
 
471
- #: widgets/button/button.php:137, widgets/contact/contact.php:607, widgets/hero/hero.php:254, widgets/layout-slider/layout-slider.php:193, widgets/testimonial/testimonial.php:227
472
  msgid "Text color"
473
  msgstr ""
474
 
@@ -580,18 +572,14 @@ msgstr ""
580
  msgid "Adds a rel attribute to the button link."
581
  msgstr ""
582
 
583
- #: widgets/contact/contact.php:4
584
- msgid "A light weight contact form builder."
585
  msgstr ""
586
 
587
  #: widgets/contact/contact.php:17
588
  msgid "SiteOrigin Contact Form"
589
  msgstr ""
590
 
591
- #: widgets/contact/contact.php:19
592
- msgid "Create a simple contact form for your users to get hold of you."
593
- msgstr ""
594
-
595
  #: widgets/contact/contact.php:49, widgets/contact/contact.php:93
596
  msgid "Contact Us"
597
  msgstr ""
@@ -812,7 +800,7 @@ msgstr ""
812
  msgid "Challenge type"
813
  msgstr ""
814
 
815
- #: widgets/contact/contact.php:276, widgets/image-grid/image-grid.php:53, widgets/image-grid/image-grid.php:62, widgets/price-table/price-table.php:70, widgets/simple-masonry/simple-masonry.php:55, widgets/testimonial/testimonial.php:72, widgets/testimonial/testimonial.php:189
816
  msgid "Image"
817
  msgstr ""
818
 
@@ -928,7 +916,7 @@ msgstr ""
928
  msgid "Margin"
929
  msgstr ""
930
 
931
- #: widgets/contact/contact.php:451, widgets/google-map/google-map.php:98, widgets/hero/hero.php:165, widgets/layout-slider/layout-slider.php:126
932
  msgid "Height"
933
  msgstr ""
934
 
@@ -936,7 +924,7 @@ msgstr ""
936
  msgid "Text Area Height"
937
  msgstr ""
938
 
939
- #: widgets/contact/contact.php:459, widgets/hero/hero.php:89, widgets/layout-slider/layout-slider.php:54
940
  msgid "Background"
941
  msgstr ""
942
 
@@ -1097,7 +1085,7 @@ msgctxt "The name of who sent this email"
1097
  msgid "From"
1098
  msgstr ""
1099
 
1100
- #: widgets/cta/cta.php:4
1101
  msgid "A simple call-to-action widget. You can do what ever you want with a call-to-action widget."
1102
  msgstr ""
1103
 
@@ -1105,10 +1093,6 @@ msgstr ""
1105
  msgid "SiteOrigin Call-to-action"
1106
  msgstr ""
1107
 
1108
- #: widgets/cta/cta.php:18
1109
- msgid "A simple call-to-action widget with massive power."
1110
- msgstr ""
1111
-
1112
  #: widgets/cta/cta.php:69, widgets/price-table/price-table.php:65
1113
  msgid "Subtitle"
1114
  msgstr ""
@@ -1133,7 +1117,7 @@ msgstr ""
1133
  msgid "Get more font customization options with %sSiteOrigin Premium%s"
1134
  msgstr ""
1135
 
1136
- #: widgets/editor/editor.php:4
1137
  msgid "A widget which allows editing of content using the TinyMCE editor."
1138
  msgstr ""
1139
 
@@ -1141,10 +1125,6 @@ msgstr ""
1141
  msgid "SiteOrigin Editor"
1142
  msgstr ""
1143
 
1144
- #: widgets/editor/editor.php:19
1145
- msgid "A rich-text, text editor."
1146
- msgstr ""
1147
-
1148
  #: widgets/editor/editor.php:43
1149
  msgid "Automatically add paragraphs"
1150
  msgstr ""
@@ -1153,11 +1133,11 @@ msgstr ""
1153
  msgid "Enable the \"Automatically add paragraphs\" setting by default."
1154
  msgstr ""
1155
 
1156
- #: widgets/editor/editor.php:148
1157
  msgid "Use Google Fonts right inside the Editor Widget using %sSiteOrigin Premium%s"
1158
  msgstr ""
1159
 
1160
- #: widgets/features/features.php:4
1161
  msgid "Displays a block of features with icons."
1162
  msgstr ""
1163
 
@@ -1165,10 +1145,6 @@ msgstr ""
1165
  msgid "SiteOrigin Features"
1166
  msgstr ""
1167
 
1168
- #: widgets/features/features.php:16
1169
- msgid "Displays a list of features."
1170
- msgstr ""
1171
-
1172
  #: widgets/features/features.php:43, widgets/price-table/price-table.php:101
1173
  msgid "Features"
1174
  msgstr ""
@@ -1293,7 +1269,7 @@ msgstr ""
1293
  msgid "This setting controls when the features widget will collapse for mobile devices. The default value is 520px"
1294
  msgstr ""
1295
 
1296
- #: widgets/google-map/google-map.php:4
1297
  msgid "A highly customisable Google Maps widget. Help your site find its place and give it some direction."
1298
  msgstr ""
1299
 
@@ -1301,10 +1277,6 @@ msgstr ""
1301
  msgid "SiteOrigin Google Maps"
1302
  msgstr ""
1303
 
1304
- #: widgets/google-map/google-map.php:19
1305
- msgid "A Google Maps widget."
1306
- msgstr ""
1307
-
1308
  #: widgets/google-map/google-map.php:47
1309
  msgid "Map center"
1310
  msgstr ""
@@ -1701,7 +1673,7 @@ msgstr ""
1701
  msgid "Get a curated list of predefined map styles with %sSiteOrigin Premium%s"
1702
  msgstr ""
1703
 
1704
- #: widgets/headline/headline.php:4
1705
  msgid "A headline to headline all headlines."
1706
  msgstr ""
1707
 
@@ -1709,10 +1681,6 @@ msgstr ""
1709
  msgid "SiteOrigin Headline"
1710
  msgstr ""
1711
 
1712
- #: widgets/headline/headline.php:19
1713
- msgid "A headline widget."
1714
- msgstr ""
1715
-
1716
  #: widgets/headline/headline.php:38, widgets/headline/headline.php:238
1717
  msgid "Headline"
1718
  msgstr ""
@@ -1765,11 +1733,11 @@ msgstr ""
1765
  msgid "Sub Headline"
1766
  msgstr ""
1767
 
1768
- #: widgets/headline/headline.php:247, widgets/hero/hero.php:221
1769
  msgid "Use FitText"
1770
  msgstr ""
1771
 
1772
- #: widgets/headline/headline.php:248, widgets/hero/hero.php:222
1773
  msgid "Dynamically adjust your heading font size based on screen size."
1774
  msgstr ""
1775
 
@@ -1777,7 +1745,7 @@ msgstr ""
1777
  msgid "FitText Compressor Strength"
1778
  msgstr ""
1779
 
1780
- #: widgets/headline/headline.php:262, widgets/hero/hero.php:236
1781
  msgid "The higher the value, the more your headings will be scaled down. Values above 1 are allowed."
1782
  msgstr ""
1783
 
@@ -1805,7 +1773,7 @@ msgstr ""
1805
  msgid "Add [buttons] shortcode to the content to insert these buttons."
1806
  msgstr ""
1807
 
1808
- #: widgets/hero/hero.php:93, widgets/layout-slider/layout-slider.php:58, widgets/slider/slider.php:57
1809
  msgid "Background image"
1810
  msgstr ""
1811
 
@@ -1813,107 +1781,115 @@ msgstr ""
1813
  msgid "Image size"
1814
  msgstr ""
1815
 
1816
- #: widgets/hero/hero.php:105, widgets/layout-slider/layout-slider.php:65, widgets/slider/slider.php:68
1817
  msgid "Background image type"
1818
  msgstr ""
1819
 
1820
- #: widgets/hero/hero.php:107, widgets/slider/slider.php:70
1821
  msgid "Cover"
1822
  msgstr ""
1823
 
1824
- #: widgets/hero/hero.php:113, widgets/layout-slider/layout-slider.php:74
1825
  msgid "Background image opacity"
1826
  msgstr ""
1827
 
1828
- #: widgets/hero/hero.php:133, widgets/layout-slider/layout-slider.php:94
1829
  msgid "Open URL in a new window"
1830
  msgstr ""
1831
 
1832
- #: widgets/hero/hero.php:138, widgets/layout-slider/layout-slider.php:99, widgets/slider/slider.php:44
1833
  msgid "Video"
1834
  msgstr ""
1835
 
1836
- #: widgets/hero/hero.php:139, widgets/layout-slider/layout-slider.php:100, widgets/slider/slider.php:45
1837
  msgid "Background videos"
1838
  msgstr ""
1839
 
1840
- #: widgets/hero/hero.php:154, widgets/layout-slider/layout-slider.php:115
1841
  msgid "Slider Controls"
1842
  msgstr ""
1843
 
1844
- #: widgets/hero/hero.php:160, widgets/layout-slider/layout-slider.php:121
1845
  msgid "Design and Layout"
1846
  msgstr ""
1847
 
1848
- #: widgets/hero/hero.php:171, widgets/layout-slider/layout-slider.php:131
1849
  msgid "Responsive Height"
1850
  msgstr ""
1851
 
1852
- #: widgets/hero/hero.php:177, widgets/layout-slider/layout-slider.php:136
 
 
 
 
 
 
 
 
1853
  msgid "Top and bottom padding"
1854
  msgstr ""
1855
 
1856
- #: widgets/hero/hero.php:183, widgets/layout-slider/layout-slider.php:142
1857
  msgid "Extra top padding"
1858
  msgstr ""
1859
 
1860
- #: widgets/hero/hero.php:184, widgets/layout-slider/layout-slider.php:143
1861
  msgid "Additional padding added to the top of the slider"
1862
  msgstr ""
1863
 
1864
- #: widgets/hero/hero.php:190, widgets/layout-slider/layout-slider.php:149
1865
  msgid "Side padding"
1866
  msgstr ""
1867
 
1868
- #: widgets/hero/hero.php:196, widgets/layout-slider/layout-slider.php:155
1869
  msgid "Maximum container width"
1870
  msgstr ""
1871
 
1872
- #: widgets/hero/hero.php:202
1873
  msgid "Heading font"
1874
  msgstr ""
1875
 
1876
- #: widgets/hero/hero.php:208, widgets/layout-slider/layout-slider.php:161
1877
  msgid "Heading color"
1878
  msgstr ""
1879
 
1880
- #: widgets/hero/hero.php:214
1881
  msgid "Heading size"
1882
  msgstr ""
1883
 
1884
- #: widgets/hero/hero.php:215
1885
  msgid "Enter the h1 font size. h2 - h6 will be proportionally sized based on this value."
1886
  msgstr ""
1887
 
1888
- #: widgets/hero/hero.php:235
1889
  msgid "FitText compressor strength"
1890
  msgstr ""
1891
 
1892
- #: widgets/hero/hero.php:246, widgets/layout-slider/layout-slider.php:175
1893
  msgid "Heading shadow intensity"
1894
  msgstr ""
1895
 
1896
- #: widgets/hero/hero.php:259, widgets/layout-slider/layout-slider.php:185
1897
  msgid "Text size"
1898
  msgstr ""
1899
 
1900
- #: widgets/hero/hero.php:264
1901
  msgid "Text font"
1902
  msgstr ""
1903
 
1904
- #: widgets/hero/hero.php:269
1905
  msgid "Text shadow intensity"
1906
  msgstr ""
1907
 
1908
- #: widgets/hero/hero.php:278
1909
  msgid "Link color"
1910
  msgstr ""
1911
 
1912
- #: widgets/hero/hero.php:283
1913
  msgid "Link hover color"
1914
  msgstr ""
1915
 
1916
- #: widgets/icon/icon.php:4
1917
  msgid "An iconic icon."
1918
  msgstr ""
1919
 
@@ -1921,22 +1897,14 @@ msgstr ""
1921
  msgid "SiteOrigin Icon"
1922
  msgstr ""
1923
 
1924
- #: widgets/icon/icon.php:19
1925
- msgid "An icon widget."
1926
- msgstr ""
1927
-
1928
- #: widgets/image/image.php:4
1929
- msgid "A very simple image widget."
1930
  msgstr ""
1931
 
1932
  #: widgets/image/image.php:14
1933
  msgid "SiteOrigin Image"
1934
  msgstr ""
1935
 
1936
- #: widgets/image/image.php:16
1937
- msgid "A simple image widget with massive power."
1938
- msgstr ""
1939
-
1940
  #: widgets/image/image.php:32
1941
  msgid "Image file"
1942
  msgstr ""
@@ -1957,7 +1925,7 @@ msgstr ""
1957
  msgid "Alt text"
1958
  msgstr ""
1959
 
1960
- #: widgets/image/image.php:94, widgets/image-grid/image-grid.php:81, widgets/slider/slider.php:90
1961
  msgid "Open in new window"
1962
  msgstr ""
1963
 
@@ -1981,7 +1949,7 @@ msgstr ""
1981
  msgid "Add a Lightbox to your images with %sSiteOrigin Premium%s"
1982
  msgstr ""
1983
 
1984
- #: widgets/image-grid/image-grid.php:4
1985
  msgid "Display a grid of images. Also useful for displaying client logos."
1986
  msgstr ""
1987
 
@@ -1989,10 +1957,6 @@ msgstr ""
1989
  msgid "SiteOrigin Image Grid"
1990
  msgstr ""
1991
 
1992
- #: widgets/image-grid/image-grid.php:23
1993
- msgid "Display a grid of images."
1994
- msgstr ""
1995
-
1996
  #: widgets/image-grid/image-grid.php:52, widgets/simple-masonry/simple-masonry.php:48
1997
  msgid "Images"
1998
  msgstr ""
@@ -2037,23 +2001,23 @@ msgstr ""
2037
  msgid "Slider frames"
2038
  msgstr ""
2039
 
2040
- #: widgets/layout-slider/layout-slider.php:68, widgets/slider/slider.php:71
2041
  msgid "Tile"
2042
  msgstr ""
2043
 
2044
- #: widgets/layout-slider/layout-slider.php:210
2045
  msgid "This widget requires: "
2046
  msgstr ""
2047
 
2048
- #: widgets/layout-slider/layout-slider.php:211, base/inc/fields/builder.class.php:43
2049
  msgid "SiteOrigin Page Builder"
2050
  msgstr ""
2051
 
2052
- #: widgets/layout-slider/layout-slider.php:276
2053
  msgid "This widget requires Page Builder."
2054
  msgstr ""
2055
 
2056
- #: widgets/post-carousel/post-carousel.php:4
2057
  msgid "Gives you a widget to display your posts as a carousel."
2058
  msgstr ""
2059
 
@@ -2061,10 +2025,6 @@ msgstr ""
2061
  msgid "SiteOrigin Post Carousel"
2062
  msgstr ""
2063
 
2064
- #: widgets/post-carousel/post-carousel.php:52
2065
- msgid "Display your posts as a carousel."
2066
- msgstr ""
2067
-
2068
  #: widgets/post-carousel/post-carousel.php:104
2069
  msgid "Default Thumbnail"
2070
  msgstr ""
@@ -2093,7 +2053,7 @@ msgstr ""
2093
  msgid "Posts query"
2094
  msgstr ""
2095
 
2096
- #: widgets/price-table/price-table.php:4
2097
  msgid "A powerful yet simple price table widget for your sidebars or Page Builder pages."
2098
  msgstr ""
2099
 
@@ -2101,10 +2061,6 @@ msgstr ""
2101
  msgid "SiteOrigin Price Table"
2102
  msgstr ""
2103
 
2104
- #: widgets/price-table/price-table.php:17
2105
- msgid "A simple Price Table."
2106
- msgstr ""
2107
-
2108
  #: widgets/price-table/price-table.php:47
2109
  msgid "Columns"
2110
  msgstr ""
@@ -2161,7 +2117,7 @@ msgstr ""
2161
  msgid "Equalize row heights"
2162
  msgstr ""
2163
 
2164
- #: widgets/simple-masonry/simple-masonry.php:4
2165
  msgid "A masonry layout for images. Images can link to your posts."
2166
  msgstr ""
2167
 
@@ -2169,103 +2125,95 @@ msgstr ""
2169
  msgid "SiteOrigin Simple Masonry"
2170
  msgstr ""
2171
 
2172
- #: widgets/simple-masonry/simple-masonry.php:17
2173
- msgid "A simple masonry layout widget."
2174
- msgstr ""
2175
-
2176
- #: widgets/simple-masonry/simple-masonry.php:59
2177
  msgid "Column span"
2178
  msgstr ""
2179
 
2180
- #: widgets/simple-masonry/simple-masonry.php:60
2181
  msgid "Number of columns this item should span. (Limited to number of columns selected in Layout section below.)"
2182
  msgstr ""
2183
 
2184
- #: widgets/simple-masonry/simple-masonry.php:67
2185
  msgid "Row span"
2186
  msgstr ""
2187
 
2188
- #: widgets/simple-masonry/simple-masonry.php:68
2189
  msgid "Number of rows this item should span. (Limited to number of columns selected in Layout section below.)"
2190
  msgstr ""
2191
 
2192
- #: widgets/simple-masonry/simple-masonry.php:90
2193
  msgid "Desktop Layout"
2194
  msgstr ""
2195
 
2196
- #: widgets/simple-masonry/simple-masonry.php:94, widgets/simple-masonry/simple-masonry.php:126, widgets/simple-masonry/simple-masonry.php:158
2197
  msgid "Number of columns"
2198
  msgstr ""
2199
 
2200
- #: widgets/simple-masonry/simple-masonry.php:101, widgets/simple-masonry/simple-masonry.php:133, widgets/simple-masonry/simple-masonry.php:165
2201
  msgid "Row height"
2202
  msgstr ""
2203
 
2204
- #: widgets/simple-masonry/simple-masonry.php:102, widgets/simple-masonry/simple-masonry.php:134, widgets/simple-masonry/simple-masonry.php:166
2205
  msgid "Leave blank to match calculated column width."
2206
  msgstr ""
2207
 
2208
- #: widgets/simple-masonry/simple-masonry.php:107, widgets/simple-masonry/simple-masonry.php:139, widgets/simple-masonry/simple-masonry.php:171
2209
  msgid "Gutter"
2210
  msgstr ""
2211
 
2212
- #: widgets/simple-masonry/simple-masonry.php:108, widgets/simple-masonry/simple-masonry.php:140, widgets/simple-masonry/simple-masonry.php:172
2213
  msgid "Space between masonry items."
2214
  msgstr ""
2215
 
2216
- #: widgets/simple-masonry/simple-masonry.php:115
2217
  msgid "Tablet Layout"
2218
  msgstr ""
2219
 
2220
- #: widgets/simple-masonry/simple-masonry.php:120, widgets/simple-masonry/simple-masonry.php:152
2221
  msgid "Break point"
2222
  msgstr ""
2223
 
2224
- #: widgets/simple-masonry/simple-masonry.php:121
2225
  msgid "Device width, in pixels, at which to collapse into a tablet view."
2226
  msgstr ""
2227
 
2228
- #: widgets/simple-masonry/simple-masonry.php:147
2229
  msgid "Mobile Layout"
2230
  msgstr ""
2231
 
2232
- #: widgets/simple-masonry/simple-masonry.php:153
2233
  msgid "Device width, in pixels, at which to collapse into a mobile view."
2234
  msgstr ""
2235
 
2236
- #: widgets/simple-masonry/simple-masonry.php:227
2237
  msgid "Add a Lightbox to your masonry images with %sSiteOrigin Premium%s"
2238
  msgstr ""
2239
 
2240
- #: widgets/slider/slider.php:4
2241
- msgid "A very simple slider widget."
2242
  msgstr ""
2243
 
2244
  #: widgets/slider/slider.php:16
2245
  msgid "SiteOrigin Slider"
2246
  msgstr ""
2247
 
2248
- #: widgets/slider/slider.php:18
2249
- msgid "A responsive slider widget that supports images and video."
2250
- msgstr ""
2251
-
2252
- #: widgets/slider/slider.php:63
2253
  msgid "Background Color"
2254
  msgstr ""
2255
 
2256
- #: widgets/slider/slider.php:79
2257
  msgid "Foreground image"
2258
  msgstr ""
2259
 
2260
- #: widgets/slider/slider.php:97
2261
  msgid "Controls"
2262
  msgstr ""
2263
 
2264
- #: widgets/slider/slider.php:268
2265
  msgid "Add a Lightbox to your image slides with %sSiteOrigin Premium%s"
2266
  msgstr ""
2267
 
2268
- #: widgets/social-media-buttons/social-media-buttons.php:4
2269
  msgid "Customizable buttons which link to all your social media profiles."
2270
  msgstr ""
2271
 
@@ -2273,10 +2221,6 @@ msgstr ""
2273
  msgid "SiteOrigin Social Media Buttons"
2274
  msgstr ""
2275
 
2276
- #: widgets/social-media-buttons/social-media-buttons.php:21
2277
- msgid "A social media buttons widget."
2278
- msgstr ""
2279
-
2280
  #: widgets/social-media-buttons/social-media-buttons.php:35
2281
  msgid "This setting controls when the Mobile Align setting will be used. The default value is 780px"
2282
  msgstr ""
@@ -2301,7 +2245,7 @@ msgstr ""
2301
  msgid "Add custom social networks with %sSiteOrigin Premium%s"
2302
  msgstr ""
2303
 
2304
- #: widgets/tabs/tabs.php:4
2305
  msgid "A tabby widget to switch between tabbed content panels."
2306
  msgstr ""
2307
 
@@ -2309,10 +2253,6 @@ msgstr ""
2309
  msgid "SiteOrigin Tabs"
2310
  msgstr ""
2311
 
2312
- #: widgets/tabs/tabs.php:17
2313
- msgid "A tabs widget."
2314
- msgstr ""
2315
-
2316
  #: widgets/tabs/tabs.php:51, widgets/tabs/tabs.php:101
2317
  msgid "Tabs"
2318
  msgstr ""
@@ -2337,7 +2277,7 @@ msgstr ""
2337
  msgid "Get more customization options and the ability to use widgets and layouts as your tabs content with %sSiteOrigin Premium%s"
2338
  msgstr ""
2339
 
2340
- #: widgets/taxonomy/taxonomy.php:4
2341
  msgid "Displays the selected taxonomy for the current post."
2342
  msgstr ""
2343
 
@@ -2345,10 +2285,6 @@ msgstr ""
2345
  msgid "SiteOrigin Taxonomy"
2346
  msgstr ""
2347
 
2348
- #: widgets/taxonomy/taxonomy.php:19
2349
- msgid "A taxonomy widget."
2350
- msgstr ""
2351
-
2352
  #: widgets/taxonomy/taxonomy.php:38, base/inc/fields/posts.class.php:50
2353
  msgid "Taxonomies"
2354
  msgstr ""
@@ -2365,18 +2301,14 @@ msgstr ""
2365
  msgid "Hover color"
2366
  msgstr ""
2367
 
2368
- #: widgets/testimonial/testimonial.php:4
2369
- msgid "Display some testimonials."
2370
  msgstr ""
2371
 
2372
  #: widgets/testimonial/testimonial.php:15
2373
  msgid "SiteOrigin Testimonials"
2374
  msgstr ""
2375
 
2376
- #: widgets/testimonial/testimonial.php:17
2377
- msgid "Share your product/service testimonials in a variety of different ways."
2378
- msgstr ""
2379
-
2380
  #: widgets/testimonial/testimonial.php:45
2381
  msgid "Testimonials"
2382
  msgstr ""
@@ -2485,7 +2417,7 @@ msgstr ""
2485
  msgid "Text below user"
2486
  msgstr ""
2487
 
2488
- #: widgets/video/video.php:4
2489
  msgid "Play all your self or externally hosted videos in a customizable video player."
2490
  msgstr ""
2491
 
@@ -2493,10 +2425,6 @@ msgstr ""
2493
  msgid "SiteOrigin Video Player"
2494
  msgstr ""
2495
 
2496
- #: widgets/video/video.php:20
2497
- msgid "A video player widget."
2498
- msgstr ""
2499
-
2500
  #: widgets/video/video.php:37
2501
  msgid "Video location"
2502
  msgstr ""
@@ -2618,11 +2546,11 @@ msgstr ""
2618
  msgid "Use theme font"
2619
  msgstr ""
2620
 
2621
- #: base/inc/fields/icon.class.php:33
2622
  msgid "Choose Icon"
2623
  msgstr ""
2624
 
2625
- #: base/inc/fields/icon.class.php:36, base/inc/fields/media.class.php:111
2626
  msgid "Remove"
2627
  msgstr ""
2628
 
@@ -2815,7 +2743,7 @@ msgid "Additional"
2815
  msgstr ""
2816
 
2817
  #: base/inc/fields/posts.class.php:140
2818
- msgid "Additional query arguments. See <a href=\"http://codex.wordpress.org/Function_Reference/query_posts\" target=\"_blank\" rel=\"noopener noreferrer\">query_posts</a>."
2819
  msgstr ""
2820
 
2821
  #: base/inc/fields/presets.class.php:18
125
  msgstr ""
126
 
127
  #: icons/icons.php:7
128
+ msgid "Font Awesome"
129
  msgstr ""
130
 
131
  #: icons/icons.php:8
132
+ msgid "Elegant Themes Line Icons"
133
  msgstr ""
134
 
135
  #: icons/icons.php:9
265
  msgstr ""
266
 
267
  #: icons/fontawesome/filter.php:1376
 
 
 
 
268
  msgid "Regular"
269
  msgstr ""
270
 
271
+ #: icons/fontawesome/filter.php:1377, widgets/contact/contact.php:363, widgets/contact/contact.php:480, widgets/contact/contact.php:588, widgets/contact/contact.php:666, widgets/headline/headline.php:189
272
  msgid "Solid"
273
  msgstr ""
274
 
275
+ #: icons/fontawesome/filter.php:1378
276
+ msgid "Brands"
277
+ msgstr ""
278
+
279
+ #: widgets/accordion/accordion.php:4, widgets/accordion/accordion.php:17
280
  msgid "An accordion to squeeze a lot of content into a small space."
281
  msgstr ""
282
 
284
  msgid "SiteOrigin Accordion"
285
  msgstr ""
286
 
287
+ #: widgets/accordion/accordion.php:47, widgets/accordion/accordion.php:60, widgets/contact/contact.php:48, widgets/cta/cta.php:64, widgets/editor/editor.php:33, widgets/features/features.php:136, widgets/post-carousel/post-carousel.php:98, widgets/price-table/price-table.php:42, widgets/price-table/price-table.php:61, widgets/simple-masonry/simple-masonry.php:44, widgets/simple-masonry/simple-masonry.php:84, widgets/social-media-buttons/social-media-buttons.php:54, widgets/tabs/tabs.php:47, widgets/tabs/tabs.php:60, widgets/taxonomy/taxonomy.php:34, widgets/testimonial/testimonial.php:41, widgets/video/video.php:33, base/inc/fields/posts.class.php:97
 
 
 
 
288
  msgid "Title"
289
  msgstr ""
290
 
292
  msgid "Panels"
293
  msgstr ""
294
 
295
+ #: widgets/accordion/accordion.php:64, widgets/hero/hero.php:62, widgets/layout-slider/layout-slider.php:56, widgets/tabs/tabs.php:64
296
  msgid "Content"
297
  msgstr ""
298
 
320
  msgid "Headings"
321
  msgstr ""
322
 
323
+ #: widgets/accordion/accordion.php:90, widgets/accordion/accordion.php:128, widgets/contact/contact.php:336, widgets/contact/contact.php:569, widgets/cta/cta.php:78, widgets/hero/hero.php:122, widgets/layout-slider/layout-slider.php:90, widgets/social-media-buttons/social-media-buttons.php:86, widgets/tabs/tabs.php:86, widgets/tabs/tabs.php:106, widgets/tabs/tabs.php:150
324
  msgid "Background color"
325
  msgstr ""
326
 
360
  msgid "Get more customization options and the ability to use widgets and layouts as your accordion content with %sSiteOrigin Premium%s"
361
  msgstr ""
362
 
363
+ #: widgets/button/button.php:4, widgets/button/button.php:17
364
  msgid "A powerful yet simple button widget for your sidebars or Page Builder pages."
365
  msgstr ""
366
 
368
  msgid "SiteOrigin Button"
369
  msgstr ""
370
 
 
 
 
 
371
  #: widgets/button/button.php:46, widgets/price-table/price-table.php:93
372
  msgid "Button text"
373
  msgstr ""
374
 
375
+ #: widgets/button/button.php:51, widgets/google-map/google-map.php:103, widgets/headline/headline.php:47, widgets/headline/headline.php:118, widgets/hero/hero.php:128, widgets/icon/icon.php:57, widgets/image/image.php:89, widgets/layout-slider/layout-slider.php:96, widgets/simple-masonry/simple-masonry.php:88, widgets/slider/slider.php:96
376
  msgid "Destination URL"
377
  msgstr ""
378
 
379
+ #: widgets/button/button.php:57, widgets/google-map/google-map.php:114, widgets/headline/headline.php:52, widgets/headline/headline.php:123, widgets/icon/icon.php:63, widgets/simple-masonry/simple-masonry.php:93, widgets/social-media-buttons/social-media-buttons.php:97, widgets/taxonomy/taxonomy.php:65, widgets/testimonial/testimonial.php:94
380
  msgid "Open in a new window"
381
  msgstr ""
382
 
460
  msgid "Button color"
461
  msgstr ""
462
 
463
+ #: widgets/button/button.php:137, widgets/contact/contact.php:607, widgets/hero/hero.php:260, widgets/layout-slider/layout-slider.php:206, widgets/testimonial/testimonial.php:227
464
  msgid "Text color"
465
  msgstr ""
466
 
572
  msgid "Adds a rel attribute to the button link."
573
  msgstr ""
574
 
575
+ #: widgets/contact/contact.php:4, widgets/contact/contact.php:19
576
+ msgid "A lightweight contact form builder."
577
  msgstr ""
578
 
579
  #: widgets/contact/contact.php:17
580
  msgid "SiteOrigin Contact Form"
581
  msgstr ""
582
 
 
 
 
 
583
  #: widgets/contact/contact.php:49, widgets/contact/contact.php:93
584
  msgid "Contact Us"
585
  msgstr ""
800
  msgid "Challenge type"
801
  msgstr ""
802
 
803
+ #: widgets/contact/contact.php:276, widgets/image-grid/image-grid.php:53, widgets/image-grid/image-grid.php:62, widgets/price-table/price-table.php:70, widgets/simple-masonry/simple-masonry.php:64, widgets/testimonial/testimonial.php:72, widgets/testimonial/testimonial.php:189
804
  msgid "Image"
805
  msgstr ""
806
 
916
  msgid "Margin"
917
  msgstr ""
918
 
919
+ #: widgets/contact/contact.php:451, widgets/google-map/google-map.php:98, widgets/hero/hero.php:165, widgets/layout-slider/layout-slider.php:133
920
  msgid "Height"
921
  msgstr ""
922
 
924
  msgid "Text Area Height"
925
  msgstr ""
926
 
927
+ #: widgets/contact/contact.php:459, widgets/hero/hero.php:89, widgets/layout-slider/layout-slider.php:61
928
  msgid "Background"
929
  msgstr ""
930
 
1085
  msgid "From"
1086
  msgstr ""
1087
 
1088
+ #: widgets/cta/cta.php:4, widgets/cta/cta.php:18
1089
  msgid "A simple call-to-action widget. You can do what ever you want with a call-to-action widget."
1090
  msgstr ""
1091
 
1093
  msgid "SiteOrigin Call-to-action"
1094
  msgstr ""
1095
 
 
 
 
 
1096
  #: widgets/cta/cta.php:69, widgets/price-table/price-table.php:65
1097
  msgid "Subtitle"
1098
  msgstr ""
1117
  msgid "Get more font customization options with %sSiteOrigin Premium%s"
1118
  msgstr ""
1119
 
1120
+ #: widgets/editor/editor.php:4, widgets/editor/editor.php:19
1121
  msgid "A widget which allows editing of content using the TinyMCE editor."
1122
  msgstr ""
1123
 
1125
  msgid "SiteOrigin Editor"
1126
  msgstr ""
1127
 
 
 
 
 
1128
  #: widgets/editor/editor.php:43
1129
  msgid "Automatically add paragraphs"
1130
  msgstr ""
1133
  msgid "Enable the \"Automatically add paragraphs\" setting by default."
1134
  msgstr ""
1135
 
1136
+ #: widgets/editor/editor.php:150
1137
  msgid "Use Google Fonts right inside the Editor Widget using %sSiteOrigin Premium%s"
1138
  msgstr ""
1139
 
1140
+ #: widgets/features/features.php:4, widgets/features/features.php:16
1141
  msgid "Displays a block of features with icons."
1142
  msgstr ""
1143
 
1145
  msgid "SiteOrigin Features"
1146
  msgstr ""
1147
 
 
 
 
 
1148
  #: widgets/features/features.php:43, widgets/price-table/price-table.php:101
1149
  msgid "Features"
1150
  msgstr ""
1269
  msgid "This setting controls when the features widget will collapse for mobile devices. The default value is 520px"
1270
  msgstr ""
1271
 
1272
+ #: widgets/google-map/google-map.php:4, widgets/google-map/google-map.php:19
1273
  msgid "A highly customisable Google Maps widget. Help your site find its place and give it some direction."
1274
  msgstr ""
1275
 
1277
  msgid "SiteOrigin Google Maps"
1278
  msgstr ""
1279
 
 
 
 
 
1280
  #: widgets/google-map/google-map.php:47
1281
  msgid "Map center"
1282
  msgstr ""
1673
  msgid "Get a curated list of predefined map styles with %sSiteOrigin Premium%s"
1674
  msgstr ""
1675
 
1676
+ #: widgets/headline/headline.php:4, widgets/headline/headline.php:19
1677
  msgid "A headline to headline all headlines."
1678
  msgstr ""
1679
 
1681
  msgid "SiteOrigin Headline"
1682
  msgstr ""
1683
 
 
 
 
 
1684
  #: widgets/headline/headline.php:38, widgets/headline/headline.php:238
1685
  msgid "Headline"
1686
  msgstr ""
1733
  msgid "Sub Headline"
1734
  msgstr ""
1735
 
1736
+ #: widgets/headline/headline.php:247, widgets/hero/hero.php:227
1737
  msgid "Use FitText"
1738
  msgstr ""
1739
 
1740
+ #: widgets/headline/headline.php:248, widgets/hero/hero.php:228
1741
  msgid "Dynamically adjust your heading font size based on screen size."
1742
  msgstr ""
1743
 
1745
  msgid "FitText Compressor Strength"
1746
  msgstr ""
1747
 
1748
+ #: widgets/headline/headline.php:262, widgets/hero/hero.php:242
1749
  msgid "The higher the value, the more your headings will be scaled down. Values above 1 are allowed."
1750
  msgstr ""
1751
 
1773
  msgid "Add [buttons] shortcode to the content to insert these buttons."
1774
  msgstr ""
1775
 
1776
+ #: widgets/hero/hero.php:93, widgets/layout-slider/layout-slider.php:65, widgets/slider/slider.php:68
1777
  msgid "Background image"
1778
  msgstr ""
1779
 
1781
  msgid "Image size"
1782
  msgstr ""
1783
 
1784
+ #: widgets/hero/hero.php:105, widgets/layout-slider/layout-slider.php:72, widgets/slider/slider.php:79
1785
  msgid "Background image type"
1786
  msgstr ""
1787
 
1788
+ #: widgets/hero/hero.php:107, widgets/slider/slider.php:81
1789
  msgid "Cover"
1790
  msgstr ""
1791
 
1792
+ #: widgets/hero/hero.php:113, widgets/layout-slider/layout-slider.php:81
1793
  msgid "Background image opacity"
1794
  msgstr ""
1795
 
1796
+ #: widgets/hero/hero.php:133, widgets/layout-slider/layout-slider.php:101
1797
  msgid "Open URL in a new window"
1798
  msgstr ""
1799
 
1800
+ #: widgets/hero/hero.php:138, widgets/layout-slider/layout-slider.php:106, widgets/slider/slider.php:55
1801
  msgid "Video"
1802
  msgstr ""
1803
 
1804
+ #: widgets/hero/hero.php:139, widgets/layout-slider/layout-slider.php:107, widgets/slider/slider.php:56
1805
  msgid "Background videos"
1806
  msgstr ""
1807
 
1808
+ #: widgets/hero/hero.php:154, widgets/layout-slider/layout-slider.php:122
1809
  msgid "Slider Controls"
1810
  msgstr ""
1811
 
1812
+ #: widgets/hero/hero.php:160, widgets/layout-slider/layout-slider.php:128
1813
  msgid "Design and Layout"
1814
  msgstr ""
1815
 
1816
+ #: widgets/hero/hero.php:171, widgets/layout-slider/layout-slider.php:138
1817
  msgid "Responsive Height"
1818
  msgstr ""
1819
 
1820
+ #: widgets/hero/hero.php:177, widgets/layout-slider/layout-slider.php:143
1821
+ msgid "Vertically center align slide contents"
1822
+ msgstr ""
1823
+
1824
+ #: widgets/hero/hero.php:178, widgets/layout-slider/layout-slider.php:144
1825
+ msgid "For perfect centering, consider setting the Extra top padding setting to 0 when enabling this setting."
1826
+ msgstr ""
1827
+
1828
+ #: widgets/hero/hero.php:183, widgets/layout-slider/layout-slider.php:149
1829
  msgid "Top and bottom padding"
1830
  msgstr ""
1831
 
1832
+ #: widgets/hero/hero.php:189, widgets/layout-slider/layout-slider.php:155
1833
  msgid "Extra top padding"
1834
  msgstr ""
1835
 
1836
+ #: widgets/hero/hero.php:190, widgets/layout-slider/layout-slider.php:156
1837
  msgid "Additional padding added to the top of the slider"
1838
  msgstr ""
1839
 
1840
+ #: widgets/hero/hero.php:196, widgets/layout-slider/layout-slider.php:162
1841
  msgid "Side padding"
1842
  msgstr ""
1843
 
1844
+ #: widgets/hero/hero.php:202, widgets/layout-slider/layout-slider.php:168
1845
  msgid "Maximum container width"
1846
  msgstr ""
1847
 
1848
+ #: widgets/hero/hero.php:208
1849
  msgid "Heading font"
1850
  msgstr ""
1851
 
1852
+ #: widgets/hero/hero.php:214, widgets/layout-slider/layout-slider.php:174
1853
  msgid "Heading color"
1854
  msgstr ""
1855
 
1856
+ #: widgets/hero/hero.php:220
1857
  msgid "Heading size"
1858
  msgstr ""
1859
 
1860
+ #: widgets/hero/hero.php:221
1861
  msgid "Enter the h1 font size. h2 - h6 will be proportionally sized based on this value."
1862
  msgstr ""
1863
 
1864
+ #: widgets/hero/hero.php:241
1865
  msgid "FitText compressor strength"
1866
  msgstr ""
1867
 
1868
+ #: widgets/hero/hero.php:252, widgets/layout-slider/layout-slider.php:188
1869
  msgid "Heading shadow intensity"
1870
  msgstr ""
1871
 
1872
+ #: widgets/hero/hero.php:265, widgets/layout-slider/layout-slider.php:198
1873
  msgid "Text size"
1874
  msgstr ""
1875
 
1876
+ #: widgets/hero/hero.php:270
1877
  msgid "Text font"
1878
  msgstr ""
1879
 
1880
+ #: widgets/hero/hero.php:275
1881
  msgid "Text shadow intensity"
1882
  msgstr ""
1883
 
1884
+ #: widgets/hero/hero.php:284
1885
  msgid "Link color"
1886
  msgstr ""
1887
 
1888
+ #: widgets/hero/hero.php:289
1889
  msgid "Link hover color"
1890
  msgstr ""
1891
 
1892
+ #: widgets/icon/icon.php:4, widgets/icon/icon.php:19
1893
  msgid "An iconic icon."
1894
  msgstr ""
1895
 
1897
  msgid "SiteOrigin Icon"
1898
  msgstr ""
1899
 
1900
+ #: widgets/image/image.php:4, widgets/image/image.php:16
1901
+ msgid "A simple image widget with massive power."
 
 
 
 
1902
  msgstr ""
1903
 
1904
  #: widgets/image/image.php:14
1905
  msgid "SiteOrigin Image"
1906
  msgstr ""
1907
 
 
 
 
 
1908
  #: widgets/image/image.php:32
1909
  msgid "Image file"
1910
  msgstr ""
1925
  msgid "Alt text"
1926
  msgstr ""
1927
 
1928
+ #: widgets/image/image.php:94, widgets/image-grid/image-grid.php:81, widgets/slider/slider.php:101
1929
  msgid "Open in new window"
1930
  msgstr ""
1931
 
1949
  msgid "Add a Lightbox to your images with %sSiteOrigin Premium%s"
1950
  msgstr ""
1951
 
1952
+ #: widgets/image-grid/image-grid.php:4, widgets/image-grid/image-grid.php:23
1953
  msgid "Display a grid of images. Also useful for displaying client logos."
1954
  msgstr ""
1955
 
1957
  msgid "SiteOrigin Image Grid"
1958
  msgstr ""
1959
 
 
 
 
 
1960
  #: widgets/image-grid/image-grid.php:52, widgets/simple-masonry/simple-masonry.php:48
1961
  msgid "Images"
1962
  msgstr ""
2001
  msgid "Slider frames"
2002
  msgstr ""
2003
 
2004
+ #: widgets/layout-slider/layout-slider.php:75, widgets/slider/slider.php:82
2005
  msgid "Tile"
2006
  msgstr ""
2007
 
2008
+ #: widgets/layout-slider/layout-slider.php:223
2009
  msgid "This widget requires: "
2010
  msgstr ""
2011
 
2012
+ #: widgets/layout-slider/layout-slider.php:224, base/inc/fields/builder.class.php:43
2013
  msgid "SiteOrigin Page Builder"
2014
  msgstr ""
2015
 
2016
+ #: widgets/layout-slider/layout-slider.php:289
2017
  msgid "This widget requires Page Builder."
2018
  msgstr ""
2019
 
2020
+ #: widgets/post-carousel/post-carousel.php:4, widgets/post-carousel/post-carousel.php:52
2021
  msgid "Gives you a widget to display your posts as a carousel."
2022
  msgstr ""
2023
 
2025
  msgid "SiteOrigin Post Carousel"
2026
  msgstr ""
2027
 
 
 
 
 
2028
  #: widgets/post-carousel/post-carousel.php:104
2029
  msgid "Default Thumbnail"
2030
  msgstr ""
2053
  msgid "Posts query"
2054
  msgstr ""
2055
 
2056
+ #: widgets/price-table/price-table.php:4, widgets/price-table/price-table.php:17
2057
  msgid "A powerful yet simple price table widget for your sidebars or Page Builder pages."
2058
  msgstr ""
2059
 
2061
  msgid "SiteOrigin Price Table"
2062
  msgstr ""
2063
 
 
 
 
 
2064
  #: widgets/price-table/price-table.php:47
2065
  msgid "Columns"
2066
  msgstr ""
2117
  msgid "Equalize row heights"
2118
  msgstr ""
2119
 
2120
+ #: widgets/simple-masonry/simple-masonry.php:4, widgets/simple-masonry/simple-masonry.php:17
2121
  msgid "A masonry layout for images. Images can link to your posts."
2122
  msgstr ""
2123
 
2125
  msgid "SiteOrigin Simple Masonry"
2126
  msgstr ""
2127
 
2128
+ #: widgets/simple-masonry/simple-masonry.php:68
 
 
 
 
2129
  msgid "Column span"
2130
  msgstr ""
2131
 
2132
+ #: widgets/simple-masonry/simple-masonry.php:69
2133
  msgid "Number of columns this item should span. (Limited to number of columns selected in Layout section below.)"
2134
  msgstr ""
2135
 
2136
+ #: widgets/simple-masonry/simple-masonry.php:76
2137
  msgid "Row span"
2138
  msgstr ""
2139
 
2140
+ #: widgets/simple-masonry/simple-masonry.php:77
2141
  msgid "Number of rows this item should span. (Limited to number of columns selected in Layout section below.)"
2142
  msgstr ""
2143
 
2144
+ #: widgets/simple-masonry/simple-masonry.php:99
2145
  msgid "Desktop Layout"
2146
  msgstr ""
2147
 
2148
+ #: widgets/simple-masonry/simple-masonry.php:103, widgets/simple-masonry/simple-masonry.php:135, widgets/simple-masonry/simple-masonry.php:167
2149
  msgid "Number of columns"
2150
  msgstr ""
2151
 
2152
+ #: widgets/simple-masonry/simple-masonry.php:110, widgets/simple-masonry/simple-masonry.php:142, widgets/simple-masonry/simple-masonry.php:174
2153
  msgid "Row height"
2154
  msgstr ""
2155
 
2156
+ #: widgets/simple-masonry/simple-masonry.php:111, widgets/simple-masonry/simple-masonry.php:143, widgets/simple-masonry/simple-masonry.php:175
2157
  msgid "Leave blank to match calculated column width."
2158
  msgstr ""
2159
 
2160
+ #: widgets/simple-masonry/simple-masonry.php:116, widgets/simple-masonry/simple-masonry.php:148, widgets/simple-masonry/simple-masonry.php:180
2161
  msgid "Gutter"
2162
  msgstr ""
2163
 
2164
+ #: widgets/simple-masonry/simple-masonry.php:117, widgets/simple-masonry/simple-masonry.php:149, widgets/simple-masonry/simple-masonry.php:181
2165
  msgid "Space between masonry items."
2166
  msgstr ""
2167
 
2168
+ #: widgets/simple-masonry/simple-masonry.php:124
2169
  msgid "Tablet Layout"
2170
  msgstr ""
2171
 
2172
+ #: widgets/simple-masonry/simple-masonry.php:129, widgets/simple-masonry/simple-masonry.php:161
2173
  msgid "Break point"
2174
  msgstr ""
2175
 
2176
+ #: widgets/simple-masonry/simple-masonry.php:130
2177
  msgid "Device width, in pixels, at which to collapse into a tablet view."
2178
  msgstr ""
2179
 
2180
+ #: widgets/simple-masonry/simple-masonry.php:156
2181
  msgid "Mobile Layout"
2182
  msgstr ""
2183
 
2184
+ #: widgets/simple-masonry/simple-masonry.php:162
2185
  msgid "Device width, in pixels, at which to collapse into a mobile view."
2186
  msgstr ""
2187
 
2188
+ #: widgets/simple-masonry/simple-masonry.php:236
2189
  msgid "Add a Lightbox to your masonry images with %sSiteOrigin Premium%s"
2190
  msgstr ""
2191
 
2192
+ #: widgets/slider/slider.php:4, widgets/slider/slider.php:18
2193
+ msgid "A responsive slider widget that supports images and video."
2194
  msgstr ""
2195
 
2196
  #: widgets/slider/slider.php:16
2197
  msgid "SiteOrigin Slider"
2198
  msgstr ""
2199
 
2200
+ #: widgets/slider/slider.php:74
 
 
 
 
2201
  msgid "Background Color"
2202
  msgstr ""
2203
 
2204
+ #: widgets/slider/slider.php:90
2205
  msgid "Foreground image"
2206
  msgstr ""
2207
 
2208
+ #: widgets/slider/slider.php:108
2209
  msgid "Controls"
2210
  msgstr ""
2211
 
2212
+ #: widgets/slider/slider.php:281
2213
  msgid "Add a Lightbox to your image slides with %sSiteOrigin Premium%s"
2214
  msgstr ""
2215
 
2216
+ #: widgets/social-media-buttons/social-media-buttons.php:4, widgets/social-media-buttons/social-media-buttons.php:21
2217
  msgid "Customizable buttons which link to all your social media profiles."
2218
  msgstr ""
2219
 
2221
  msgid "SiteOrigin Social Media Buttons"
2222
  msgstr ""
2223
 
 
 
 
 
2224
  #: widgets/social-media-buttons/social-media-buttons.php:35
2225
  msgid "This setting controls when the Mobile Align setting will be used. The default value is 780px"
2226
  msgstr ""
2245
  msgid "Add custom social networks with %sSiteOrigin Premium%s"
2246
  msgstr ""
2247
 
2248
+ #: widgets/tabs/tabs.php:4, widgets/tabs/tabs.php:17
2249
  msgid "A tabby widget to switch between tabbed content panels."
2250
  msgstr ""
2251
 
2253
  msgid "SiteOrigin Tabs"
2254
  msgstr ""
2255
 
 
 
 
 
2256
  #: widgets/tabs/tabs.php:51, widgets/tabs/tabs.php:101
2257
  msgid "Tabs"
2258
  msgstr ""
2277
  msgid "Get more customization options and the ability to use widgets and layouts as your tabs content with %sSiteOrigin Premium%s"
2278
  msgstr ""
2279
 
2280
+ #: widgets/taxonomy/taxonomy.php:4, widgets/taxonomy/taxonomy.php:19
2281
  msgid "Displays the selected taxonomy for the current post."
2282
  msgstr ""
2283
 
2285
  msgid "SiteOrigin Taxonomy"
2286
  msgstr ""
2287
 
 
 
 
 
2288
  #: widgets/taxonomy/taxonomy.php:38, base/inc/fields/posts.class.php:50
2289
  msgid "Taxonomies"
2290
  msgstr ""
2301
  msgid "Hover color"
2302
  msgstr ""
2303
 
2304
+ #: widgets/testimonial/testimonial.php:4, widgets/testimonial/testimonial.php:17
2305
+ msgid "Share your product or service testimonials in a variety of different ways."
2306
  msgstr ""
2307
 
2308
  #: widgets/testimonial/testimonial.php:15
2309
  msgid "SiteOrigin Testimonials"
2310
  msgstr ""
2311
 
 
 
 
 
2312
  #: widgets/testimonial/testimonial.php:45
2313
  msgid "Testimonials"
2314
  msgstr ""
2417
  msgid "Text below user"
2418
  msgstr ""
2419
 
2420
+ #: widgets/video/video.php:4, widgets/video/video.php:20
2421
  msgid "Play all your self or externally hosted videos in a customizable video player."
2422
  msgstr ""
2423
 
2425
  msgid "SiteOrigin Video Player"
2426
  msgstr ""
2427
 
 
 
 
 
2428
  #: widgets/video/video.php:37
2429
  msgid "Video location"
2430
  msgstr ""
2546
  msgid "Use theme font"
2547
  msgstr ""
2548
 
2549
+ #: base/inc/fields/icon.class.php:38
2550
  msgid "Choose Icon"
2551
  msgstr ""
2552
 
2553
+ #: base/inc/fields/icon.class.php:41, base/inc/fields/media.class.php:111
2554
  msgid "Remove"
2555
  msgstr ""
2556
 
2743
  msgstr ""
2744
 
2745
  #: base/inc/fields/posts.class.php:140
2746
+ msgid "Additional query arguments. See <a href=\"https://developer.wordpress.org/reference/functions/query_posts/\" target=\"_blank\" rel=\"noopener noreferrer\">query_posts</a>."
2747
  msgstr ""
2748
 
2749
  #: base/inc/fields/presets.class.php:18
readme.txt CHANGED
@@ -1,925 +1,944 @@
1
- === SiteOrigin Widgets Bundle ===
2
- Tags: bundle, widget, button, slider, image, carousel, price table, google maps, tinymce, social links
3
- Requires at least: 4.2
4
- Tested up to: 5.4
5
- Stable tag: 1.16.0
6
- Build time: 2020-02-13T20:00:45+02:00
7
- License: GPLv3 or later
8
- Contributors: gpriday, braam-genis
9
- Donate link: https://siteorigin.com/downloads/premium/
10
-
11
- The SiteOrigin Widgets Bundle gives you a collection of widgets that you can use and customize. All the widgets are built on our powerful framework, giving you advanced forms, unlimited colours and 1500+ icons.
12
-
13
- == Description ==
14
-
15
- The SiteOrigin Widgets Bundle gives you a collection of widgets that you can use and customize. All the widgets are built on our powerful framework, giving you advanced forms, unlimited colours and 1500+ icons.
16
-
17
- Widgets are great. No matter where you’re using them. In a [Page Builder](http://siteorigin.com/page-builder/) page or on your widgetized areas. It's even compatible with other popular page building plugins.
18
-
19
- [vimeo https://vimeo.com/102103379]
20
-
21
- The collection is growing, but here’s what we have so far.
22
-
23
- * Google Maps Widget that's going places.
24
- * Button Widget that you’ll love to click.
25
- * Image Widget that’ll let you add images everywhere.
26
- * Call To Action Widget that’ll get your users performing the actions you want.
27
- * Slider Widget that slides images and HTML5 videos.
28
- * Price Table Widget that’ll help you sell more.
29
- * Post Carousel Widget that displays your posts as a carousel.
30
- * Features Widget that lets you display a set of site or service features.
31
- * Video Widget to get your videos out there.
32
- * Headline Widget to get you noticed.
33
- * Social Media Buttons which link to all your social media profiles.
34
- * Accordion Widget to compress your content.
35
- * Contact Form Widget to let people know you care.
36
- * Editor Widget let's you richly edit text anywhere.
37
- * Hero Widget that'll save your site design.
38
- * Icon Widget for when only icons will do.
39
- * Image Grid Widget that'll let you add images everywhere... in a grid.
40
- * Layout Slider Widget lets you build layouts on slides using SiteOrigin Page Builder.
41
- * Masonry Widget to add images in a masonry layout.
42
- * Tabs Widget that'll let you group content into tabbed sections.
43
- * Taxonomy Widget to display the selected taxonomy for the current post.
44
- * Testimonials Widget to show people what your users/customers think of you.
45
-
46
- Once you enable a widget, you'll be able to use it anywhere standard widgets are used. You can manage your widgets by going to Plugins > SiteOrigin Widgets in your WordPress admin.
47
-
48
- == Documentation ==
49
-
50
- [Documentation](https://siteorigin.com/widgets-bundle/getting-started/) is available on SiteOrigin.
51
-
52
- == Support ==
53
-
54
- We offer free support on the [SiteOrigin support forums](https://siteorigin.com/thread/).
55
-
56
- = Create Custom Widgets =
57
-
58
- The SiteOrigin Widgets Bundle is the perfect platform to build widgets for your theme or plugin. Read more on our [developer docs](https://siteorigin.com/docs/widgets-bundle/).
59
-
60
- == Screenshots ==
61
-
62
- 1. Manage which widgets you want enabled or disabled.
63
- 2. The button widget shows the clean, standard interface all the widgets use.
64
- 3. An example of the button widget.
65
-
66
- == Changelog ==
67
-
68
- = 1.16.0 - 11 February 2020 =
69
- * Block Editor: Fixed widget select field width and alignment.
70
- * Removed unused template files.
71
- * Contact Form: Improved checking for SiteOrigin development email addresses.
72
- * Minor styling improvements to the Classic and Block Editor admin interfaces.
73
- * Features: Added a new setting to select the H tag to be used for the title field.
74
- * Hero: If a height value is assigned, added prefilling to avoid a page jump.
75
- * Hero: Added `font-display: swap` for Google font imports.
76
- * Layout Slider: If a height value is assigned, added prefilling to avoid a page jump.
77
- * Image Grid: Added a class of `sow-image-grid-image_html` to each image. Can be used to exclude images from Lazy Loading plugins.
78
- * Simple Masonry: Added a class of `sow-masonry-grid-image` to each image. Can be used to exclude images from Lazy Loading plugins.
79
- * Features: Added fallback support for the Icon image field.
80
- * Testimonials: Add fallback support for the Image field.
81
- * Post Carousel: Prevented looping until all posts are loaded.
82
- * Post Carousel: Added a new setting to disable looping.
83
- * Post Carousel: Prevented scrolling past loading items and loop as soon as last item is completely visible.
84
- * Contact Form: Added disabled cursor to submit button when disabled.
85
- * Block Editor: Resolved Features widget default settings.
86
- * Tabs and Accordion: Account for accented characters.
87
- * Social Media Buttons: Allowed for multiple instances of the same network without duplicating colors.
88
- * Social Media Buttons: Ensured all icons are correctly centered.
89
- * Contact Form: Added lightweight validation for phone numbers.
90
- * Block Editor: Display author for third party widgets.
91
- * Block Editor: Added processing for the more quicktag in the Editor widget.
92
- * Tabs and Accordion: Added icon spacing.
93
- * Testimonials: Improved image sizing behavior for square images.
94
-
95
- = 1.15.9 - 11 November 2019 =
96
- * Contact Form: Improved default email address handling.
97
- * Contact Form: Improved subject field labeling.
98
- * Post Carousel: Loop the carousel when reaching the end.
99
- * Social Media Buttons: Fixed issue with responsive breakpoint unit of measurement.
100
- * Google Maps: Ensured settings modal window opens when directed to insert API key.
101
- * Google Maps: Fixed map center field when used in the Customizer.
102
- * Fixed compatibility with WordPress 5.3.
103
- * Minor code style and widget label improvements.
104
-
105
- = 1.15.8 - 20 August 2019 =
106
- * Run FitText setup on window resize events.
107
- * TinyMCE field: Copy any missing content CSS urls from main editor.
108
- * Post Carousel: Prevent scrolling past the last item.
109
- * Contact Form: Prevent sending to testing/dev emails.
110
- * Widget block: Add `h3` wrapper for widget titles.
111
- * Image widget: Remove `width:inherit;` IE8 fix for bound setting which breaks in IE11.
112
- * Sliders: Added padding to slider navigation arrows.
113
- * Accordion: Check if if anchor is present in URL and scroll to Accordion item.
114
- * Various form description and styling fixes.
115
-
116
- = 1.15.7 - 22 May 2019 =
117
- * Widget Block: Ensure changed data is retained after previewing.
118
- * Image widget: Prevent overflow of image container when wrapped in link.
119
- * Image Grid: Dispatch event to notify listeners that layout is complete.
120
- * Image Grid: Fix layout for images wrapped in links.
121
- * Image grid: Use image media title for display if title isn't set in the widget form.
122
- * Layout Slider: Remove header and text style fields.
123
- * Remove Autoptimize cache clearing as it detects changes automatically.
124
- * Update FontAwesome icons.
125
- * Google Maps location field: Ensure value is retained after preview in the block editor.
126
- * Prevent issue in SiteOrigin Layout Block when `sowb` hasn't been defined.
127
-
128
- = 1.15.6 - 29 April 2019 =
129
- * Image: Fix images vertical stretching.
130
- * Image: Fix widths for images wrapped in links.
131
- * Google Maps Location Field: Remove some unnecessary use of jQuery to avoid `$ is not a function` errors.
132
- * Google Maps Location Field: Check if matchError exists before accessing.
133
-
134
- = 1.15.5 - 25 April 2019 =
135
- * Removed admin notice for new widgets.
136
- * Slider Base Widget: Removed unused background videos height setting.
137
- * Price Table: Recalc equalized heights when window size or orientation changes.
138
- * Google Maps location field: Use value in sanitization if already an array.
139
- * Add compatibility for Autoptimize.
140
- * Simple Masonry: Ensure all available width is used for layout.
141
- * Image: Change alignment to use `display:flex` instead of `text-align`.
142
-
143
- = 1.15.4 - 27 March 2019 =
144
- * Slider field: Live updates for display value.
145
- * Widget block: Show error if missing or invalid widget data.
146
- * Google Maps: Add more links to relevant docs for enabling required APIs.
147
- * Google Maps Location field: Catch API key errors and display notice.
148
- * Run FitText resizer on `setup_widgets` too.
149
- * Add font url as property of font info object.
150
- * Image grid: Use opacity for initial hide of images so that size may still be detected.
151
- * Google Maps: Detect draggable or scroll_zoom before running setting migration.
152
- * Accordion and Tabs: Trigger window resize on start of animation.
153
- * Icon: Prevent undefined index notices.
154
-
155
- = 1.15.3 - 6 March 2019 =
156
- * Image grid: Fallback support, alt text, use measurement fields.
157
- * Features: Fix responsive layout.
158
- * Google Maps: Update to use gesture handling and separate zoom level for mobile.
159
- * Google Maps: Default height when height field is empty.
160
- * Sliders: Option to always show navigation on mobile devices.
161
- * Accordion: Keyboard navigation.
162
- * Beaver Builder: Fix icons and widgets not saving.
163
- * Video: Allow using YouTube embed URLs.
164
- * Post Carousel: Accessibility improvements.
165
- * Escape namespaced widgets in previews.
166
- * Flag additional metaboxes as incompatible with the block editor.
167
- * Fix state emitters for sub-widget fields.
168
- * Google Maps: Remove API key field from widget form, in favor of global API key field.
169
- * Google Maps: Display notice when API key missing.
170
- * Contact form: Prevent double nonce.
171
- * TinyMCE field: Prevent twemoji from replacing emoji in the textarea.
172
- * Widget block: Show appropriate message when widget is missing or deactivated.
173
- * Accordion: Fix open/close icon layout when set to left position.
174
- * Social Media Buttons: Prevent the phone network from opening in a new window.
175
- * Google Maps: Add map styles filter.
176
- * Image radio field: New field created.
177
- * Posts field: Option to specify allowed post types.
178
- * Contact form: Add description to reCAPTCHA field specifying reCAPTCHA v2.
179
-
180
- = 1.15.2 - 18 February 2019 =
181
- * Tabs: Set default tab position to top.
182
-
183
- = 1.15.1 - 15 February 2019 =
184
- * Google maps: Use correct locations for static maps.
185
-
186
- = 1.15.0 - 14 February 2019 =
187
- * Location field: New specialized admin form field which autocompletes addresses using the Google Maps places library.
188
- * Google maps: Moved global API key override to `modify_instance` to make key available in admin form too.
189
- * Google maps: Auto-migration of locations to new location field format.
190
- * Update LESS PHP library with fixes for PHP 7.3 compatibility.
191
- * Features: Apply text styles to all features content, not just `<p>` tags.
192
- * Social Media: New networks: Bandcamp, Goodreads, Telegram, Strava, Blogger.
193
- * Accordion: Fix issue preventing use of numbers in panel titles.
194
- * Block editor: Preview fixes.
195
- * Beaver Builder compat: Fix widgets failing to update and CSS for FontAwesome icons.
196
-
197
- = 1.14.1 - 9 January 2019 =
198
- * Icon field: Set correct value of currently selected icon for non-FA icons.
199
- * Icon field: Avoid requiring that third party icon families include a `filter.php` file.
200
- * Widget block: Use JS array reduce function instead of lodash.
201
- * Allow widgets registered by instance.
202
- * Multi-measurement field: Fix layout.
203
- * Block editor: Send widgetData when fetching widget forms.
204
- * Tinymce field: Prevent JS console errors for hidden fields.
205
- * Order field: Additional sanitization before rendering.
206
-
207
- = 1.14.0 - 4 January 2019 =
208
- * Accordion: allow multiple panels with the same title.
209
- * Actions when widgets' CSS files are created/deleted.
210
- * Compat fixes for PHP 7.3
211
- * Indicate when 'setup_widgets' is triggered for previews.
212
- * Accordion: Debounce window.location.hash updates to prevent incorrect states.
213
- * Don't remove FitText window listener to ensure previously set up FitText elements still work.
214
- * Icon field: Show loading indicator while icons are loading.
215
- * Widget documentation links.
216
- * Icons: Update to use latest FontAwesome icon sets.
217
- * Sliders: Resize slides when widgets are set up.
218
- * Elementor compat: Directly enqueue necessary scripts and styles for previews.
219
- * Allow widget headers to be translated.
220
- * Accordion: Keep the clicked panel in the viewport, if it moves out.
221
- * TinyMCE field: Check if tinymce is available before using.
222
-
223
- = 1.13.4 - 6 December 2018 =
224
- * Widget block: Fix Layout Slider not being editable.
225
- * Widget block: Correct used of i18n for block editor.
226
- * Widget block: Fix previews.
227
- * Google map: Move global API key override to `modify_instance` to ensure key is available in form.
228
- * Widget block: Prevent multiple API requests.
229
-
230
- = 1.13.3 - 15 November 2018 =
231
- * Contact: Fix checkboxes and radio alignment on android.
232
- * FitText: Set minimum font size to ensure readability.
233
- * TinyMCE field: Use correct editor when block editor is present.
234
- * Google maps: Use correct info window text for markers.
235
- * TinyMCE: Remove 'editor-buttons' style enqueue causing conflicts.
236
- * TinyMCE field: Prevent adding multiple copies of media buttons.
237
- * Image widget: if no alt text is supplied add an empty alt attribute.
238
- * Repeaters: Reverted some commits causing multiple issues.
239
- * WP 5: Fixed some styles in the block editor.
240
- * Only setup form fields in the dialog when a PB edit widget dialog is opened.
241
- * Multi-measurement field: Fix autoFill in block editor and attempt to fix in PHP <= 5.3.
242
-
243
- = 1.13.2 - 31 October 2018 =
244
- * Builder field: Prevent error in PHP <= 5.4
245
- * Avoid replacing repeater item id placeholders for child repeaters.
246
- * Repeaters: In repeater setup, don't setup child repeaters.
247
-
248
- = 1.13.1 - 29 October 2018 =
249
- * Gutenberg: Alert user that changes will be lost when changing the widget type.
250
- * Tabs: Keyboard navigation and more accessibility improvements.
251
- * Google maps: Better geocoding request management.
252
- * TinyMCE field: Use correct selector for checking whether click target is editor switching tab.
253
- * Slider: Option to prevent hiding video on mobile.
254
- * Accordion: Deep-linking for child accordions.
255
- * Use inline CSS fallback if writing to file failed.
256
- * Better FitText compressor description.
257
- * Delete old widget styles when updating widgets.
258
- * Layout Slider: Resoonsive height.
259
- * Accordion: Expand when user is printing.
260
- * Features: Text case adjustments and formatting.
261
- * Beaver Builder: Dark styling.
262
- * Builder field: Allow double-encoding to allow already encoded text in editors.
263
- * Contact form: Prevent adding the anchor again if it's already been added.
264
- * Contact form: Attempt to scroll to contact form after submitting, so result is visible.
265
- * Builder field: Set data correctly from JS.
266
- * Builder field: Don't encode already JSON encoded values.
267
- * Gutenberg: Allow editing page containing deactivated widget.
268
- * Gutenberg: Reset global `$post` after enqueueing widgets' scripts and styles, which might run secondary queries.
269
-
270
- = 1.13.0 - 13 September 2018 =
271
- * SiteOrigin Widgets Gutenberg block!
272
- * Google Map: Prevent script from running further if no map canvas elements found.
273
- * Removed style to set `p` margins to zero.
274
- * Check that fallback image for static maps is not an empty string before attempting to use it.
275
- * TinyMCE: Ensure target is one of the editor tabs when switching modes.
276
- * Set values for repeaters which are direct children of section fields.
277
- * Prevent unselected radio input state emitters from affecting form states, when form values are set programmatically.
278
- * Plugin Action Links: Check if edit link is present before removal.
279
- * Social Media Buttons: Added Phone and Angelist. Changed email title text.
280
- * Metabox manager: Set empty post meta string value to array. Ensure metabox widget form values are saved when saving drafts too.
281
-
282
- = 1.12.1 - 17 July 2018 =
283
- * Contact: Allow non-string values in required field validation.
284
- * Initialize CTA, Price Table and Video JS widgets correctly when in accordion/tabs widgets.
285
-
286
- = 1.12.0 - 11 July 2018 =
287
- * Contact: Add dedicated textarea height.
288
- * Social Media Buttons: Adds WhatsApp social network.
289
- * Features: Allow icon size to use a different unit of measurement.
290
- * Repeater field: Update editor id in media buttons when duplicating item with TinyMCE editor.
291
- * Posts field: taxonomy description.
292
- * Price Table: Disable equalized row heights on mobile.
293
- * Beaver Builder: Force icon fonts.
294
- * Slider widgets: Added autoplay option for background videos.
295
- * Maps: Renamed Google maps script to more sensible `sow.google-map.js`
296
- * Editor: Prevent errors when visual editing is disabled for a user.
297
- * Optimized images.
298
- * Accordion/tabs: Trigger 'setup_widgets' to ensure any widgets in panels are initialized correctly.
299
- * Contact: Use 'From' email address if there is no email field in the form.
300
- * Hero: Filter out the align field in the button sub-widget form.
301
- * Testimonials: Switch mobile and tablet resolution width field descriptions.
302
- * Posts field: Allow clearing dates.
303
- * Font field: Use correct value for 'Helvetica Neue' and added 'Arial' option.
304
- * TA: Additional setting to allow clearing the default background colors.
305
- * Contact: Allow a value of '0' for required fields and subject values.
306
-
307
- = 1.11.8 - 12 April 2018 =
308
- * Added action just before rendering widget previews.
309
- * Editor: Removed `unwpautop`.
310
- * Editor: Ensure TinyMCE field knows whether to apply `autop` or not.
311
- * Editor: Only apply `autop` on display when using HTML editor.
312
- * Editor: Prevent `widget_text` filters from running `do_shortcode`.
313
-
314
- = 1.11.7 - 23 March 2018 =
315
- * Image: Add title alignment setting.
316
- * Button: Add max-width to ensure buttons are responsive.
317
- * Hero: New filter for frame content 'siteorigin_hero_frame_content'
318
- * Features: Don't set margin for one column left/right feature.
319
- * Updated widget icons.
320
- * Updated google web fonts.
321
-
322
- = 1.11.6 - 14 March 2018 =
323
- * Hero: Add responsive height settings.
324
- * Added pikaday jQuery plugin and register pikaday scripts for front end too.
325
- * Features: item float clearing and padding mobile specific.
326
-
327
- = 1.11.5 - 13 March 2018 =
328
- * Features: Better feature padding removal on row ends.
329
- * Sliders: WCAG 2.4.4 compliance.
330
- * Tabs: Hide widget title when no title is set.
331
- * TinyMCE field: Added setting for `wpautop` processing which is on by default.
332
- * Contact: When Gradient disabled, set basic background.
333
- * Beaver Builder compat: Only set SOWB widget form values when editing a SOWB widget.
334
- * Contact: Option to log submitter's IP address.
335
- * Add random number and set `more_entropy` to increase chance of unique form ids.
336
- * Contact: Added 'tel' field type which should show numeric keyboard on mobile.
337
- * Media field: Trigger change event when removing selected image.
338
- * Renamed the PHP LESS parser to `SiteOrigin_LessC` to avoid conflicts.
339
- * Date range field: Prevent initializing date range fields multiple times and ensure date format consistent.
340
- * Register pikaday as common script and enqueue as needed in fields.
341
- * Google Map: Show satellite map type.
342
- * Translation: Add context to From strings.
343
- * Add missing semicolons to Ionicons codes.
344
-
345
- = 1.11.4 - 7 February 2018 =
346
- * Slider: Add playsinline for Video backgrounds for iOS.
347
- * Repeater field: Trigger change events for repeater when adding, removing or duplicating items.
348
- * TinyMCE field: Removed special handling for TinyMCE fields when retrieving data. Just use field value directly.
349
- * Fixed build overwriting some CSS files.
350
-
351
- = 1.11.3 - 10 January 2018 =
352
- * Hero: Add margin-top to so-widget-sow-button for spacing.
353
- * Accordion: Added overflow to prevent Image overlap.
354
- * Google Maps: Always register Google Maps script.
355
- * Social Buttons: Mobile Alignment global widget settings
356
- * Contact Form: Ability to control the width of the submit button.
357
- * Contact Form: Add alignment options for submit button.
358
- * Contact Form: Setting submit button gradient intensity to 0 removes gradient.
359
- * Contact Form: Add success and error hooks.
360
- * Accordion: Don't output widget title if not set.
361
- * Accordion: Icon title collapse fix.
362
- * Contact Form: Add placeholder for field type input.
363
- * Button: Icon placement setting.
364
- * Hero: Adjustable Paragraph text shadow.
365
- * Hero: Add font family setting for paragraphs.
366
- * Hero: Add link color picker.
367
- * Slider field: allow float values and allow specifying step size.
368
- * Contact Form: Add ability to set onclick and id for submit button.
369
- * Features: Add ability to control responsive breakpoint.
370
- * Global Settings: Add support for global settings added by themes.
371
- * Beaver Builder Compat: Don't enqueue assets when all widgets are deactivated.
372
- * Hero: Text font empty check.
373
- * Contact Form: Preserve existing location hash when contact form is submitted.
374
- * Post Selector: Only include current post id in exclusion if singular.
375
- * Copy correct radio values when duplicating repeater items.
376
- * Checkbox field: Parse string value 'false' in checkbox field sanitization.
377
-
378
- = 1.11.2 - 27 November 2017 =
379
- * Fix compatibility with Beaver Builder Lite.
380
- * Tabs: Recalculate height on resize.
381
-
382
- = 1.11.1 - 24 November 2017 =
383
- * Hero: Allow for shortcodes to work.
384
- * Fix posts field not displaying selected values when multiple selected.
385
- * Widgets Page: Fix missing icon issue on windows.
386
- * Trigger 'hide' and 'show' events in Accordion and Tabs widgets when toggling content.
387
- * Fix Google Maps widget not displaying when map is initially hidden.
388
- * Fix Beaver Builder compatibility.
389
- * Builder field: Pass builder type when setting up builder fields.
390
- * Tabs: Use correct variable for tab anchor.
391
- * Repeater field: Prevent radio inputs values being cleared in repeaters when sorting.
392
- * Accordion: Added title field.
393
- * Fix PHP version compatibility checker errors.
394
-
395
- = 1.11.0 - 7 November 2017 =
396
- * New Tabs widget!
397
- * Contact: mention it's possible to send to multiple emails.
398
- * Features: Fixes margin causing extended page.
399
- * Presets field.
400
- * Accordion: Add Repeater Label Title.
401
- * Hero: ability to select an image size.
402
- * TinyMCE field: Remember last selected editor.
403
- * Add rel="noopener noreferrer" for all 3rd party/unknown links.
404
- * Social Media Buttons Widget: comply WCAG 2.4.4
405
-
406
- = 1.10.2 - 20 October 2017 =
407
- * Fix for links sometimes not working in slider widgets.
408
- * Fix multi-measurement field labels.
409
-
410
- = 1.10.1 - 13 October 2017 =
411
- * Fix subwidget fields initializion when not contained in a section.
412
- * TinyMCE field: fix initialization in repeaters.
413
-
414
- = 1.10.0 - 11 October 2017 =
415
- * New Accordion widget!
416
- * Prevent multiple initialization of media field.
417
- * Use correct path for widget banner when defined in a theme.
418
- * Video: Added option to show/hide related YouTube videos at end of video.
419
- * Slider: Handle links inside slider frames first and then allow processing of frame background clicks.
420
- * Give repeated fields in widget fields unique ids for state handling.
421
- * New multi-measurement field.
422
- * Widget Manager Path Comparison fix. (allows for settings to work)
423
- * Button: Use `esc_js` instead of `esc_attr` for onclick.
424
-
425
- = 1.9.10 - 14 September 2017 =
426
- * TinyMCE field: fixed issue with filter for TinyMCE plugins.
427
- * Added teaser messages for SiteOrigin Premium addons.
428
-
429
- = 1.9.9 - 31 August 2017 =
430
- * Avoid using relative paths in asset URLs.
431
- * Fixed compat with latest Elementor update.
432
-
433
- = 1.9.8 - 21 August 2017 =
434
- * Use WordPress functions to exit AJAX actions.
435
- * TinyMCE field: Initialized once.
436
- * TinyMCE field: Simplified switching between TinyMCE and QuickTags.
437
- * TinyMCE field: Check if individual TinyMCE settings are encoded as JSON and decode before re-encoding all settings.
438
- * Some compat fixes for Elementor.
439
- * TinyMCE field: Temporarily disable Jetpack Grunion editor.
440
- * Use correct JS dependencies for Beaver Builder compatibility when `WP_DEBUG` not defined.
441
- * Removed unnecessary enqueues in Beaver Builder compat for dashicons and wp media scripts.
442
- * Post carousel: Only handle horizontal swipes.
443
-
444
- = 1.9.7 - 11 August 2017 =
445
- * Contact: Added user configurable field for 'From:' address.
446
- * TinyMCE field: Use editor stylesheets for new TinyMCE editor.
447
- * TinyMCE field: Use UTF-8 encoding for text output.
448
- * Sliders: Check whether `$frames` is empty before using.
449
- * Google Maps: Prevent automatic center for routes.
450
-
451
- = 1.9.6 - 4 August 2017 =
452
- * Slider: Background Video: Try embedding the video if oEmbed fails.
453
- * Contact: Added some nonce checks.
454
- * Contact: add reply-to header.
455
- * Remove elementor panel width override.
456
- * Editor: Fix TinyMCE editor button filters in WP >= 4.8.
457
- * Editor: Preserve encoded HTML entities in TinyMCE field.
458
- * TinyMCE field: Added missing `tiny_mce_before_init` filter.
459
-
460
- = 1.9.5 - 25 July 2017 =
461
- * Fixed icon field selection.
462
- * TinyMCE field is initialized when quicktags is selected.
463
- * Autocomplete field only initialized once.
464
- * Posts field sanitization handles multiple post types.
465
-
466
- = 1.9.4 - 24 July 2017 =
467
- * Using new Editor JS API for TinyMCE field.
468
- * Carousel: apply static position on `.overlay`.
469
- * Layout Slider: Add ability to set Background image to Title and spaced the code.
470
- * Add capabilities check to widget activation action.
471
- * Testimonial: Corrected typo in description and corrected formatting.
472
- * Enabling translation for "From:" in contact mail.
473
-
474
- = 1.9.3 - 3 July 2017 =
475
- * Editor: Fix settings form label.
476
- * Don't select the external fallback field as value input.
477
- * Social media buttons: Don't output calls when missing network name.
478
- * Use gettext for widget global settings dialog title.
479
- * Image: Added link attributes to template variables.
480
- * Image grid: Use `get_template_variables`.
481
- * Image grid: Template code structure a bit more readable.
482
- * Simple masonry: Assign link attributes in `get_template_variables`.
483
- * Slider widget: Output link attributes.
484
- * Features: Remove redundant paragraph from template.
485
- * Google Maps: Fix issue when no matches found in maps API error string.
486
- * Google Maps: Mention required Google Maps APIs in field descriptions.
487
- * Google Maps: Localized strings used in JS.
488
- * Elementor 1.5: Ensure widgets' setup scripts are run after editing.
489
-
490
- = 1.9.2 - 8 June 2017 =
491
- * Post Carousel: default image for posts without featured images.
492
- * Social Media Buttons: allow empty colors.
493
- * Editor: prevent text processing for cache and post content rendering.
494
- * Post selector field: Fix additional args encoding.
495
- * Post selector field: Fix taxonomy search.
496
-
497
- = 1.9.1 - 1 June 2017 =
498
- * Fixed Maps widget JS error.
499
-
500
- = 1.9 - 30 May 2017 =
501
- * Compatibility with Visual Composer.
502
- * Taxonomy widget text display.
503
- * Price table widget: option to make feature row heights equal.
504
- * New posts selector field based on other existing fields.
505
- * New autocomplete field. Currently supports showing results from posts and taxonomies.
506
- * New date-range field with option to select specific or relative dates.
507
- * Editor widget: Global widget setting for default 'autop' state.
508
- * Some layout fixes for widget forms in Elementor.
509
- * Google Maps: fallback image when maps API not available or returns error.
510
- * Contact form: Reduced intensity of disabled button styling.
511
- * Google Maps: Fix markers not displaying when queries are rate limited.
512
- * Features: Option to use specified icon size for custom icon images.
513
- * Updated FontAwesome icon set to 4.7.0
514
- * Updated IcoMoon icon set.
515
- * Contact form: Allow duplicate forms on same page.
516
- * Widget temp backup in browser storage.
517
- * Google Maps: Custom marker icon for each marker.
518
- * Option to specify default number of visible rows in icon field.
519
- * Changed PHP LESS compiler to a better maintained version.
520
-
521
- = 1.8.6 - 10 May 2017 =
522
- * Editor widget supports Jetpack Markdown.
523
- * Editor widget global setting for enabling/disabling 'autop' by default.
524
- * Allow setting FitText compressor strength in hero and headline widgets.
525
- * Fix variable name in `enqueue_registered_styles`.
526
- * Fix FitText not working previews.
527
-
528
- = 1.8.5 - 27 April 2017 =
529
- * Fixed button hover class.
530
-
531
- = 1.8.4 - 27 April 2017 =
532
- * Fixed button URLs.
533
- * Removed image `sizes` attribute when Jetpack Photon is enabled.
534
- * Fixed missing widget handling for misnamed widgets.
535
-
536
- = 1.8.3 - 26 April 2017 =
537
- * Contact Form: Improved type Validation and added empty name check
538
- * Contact Form: Add Field Design Settings
539
- * Testimonial: Add responsive image sizes settings
540
- * Added checks to prevent PHP warnings
541
- * Improved handling of empty order fields.
542
- * Small code refactoring in price table widget.
543
- * Ensure all SiteOrigin widgets are grouped together in Page Builder.
544
- * Slider: Remove slider sentinel contents to avoid things like duplicated video iframe for embedded videos
545
- * Fix TinyMCE z-index.
546
- * Headline: Fixed typo that tied subheadline new window to headline
547
- * Ensure fittext is done before setting up hero slider.
548
- * Ensure google font fields work in live editors/previews.
549
- * Features: Allow specifying position of features widgets icons.
550
- * Added * next to labels of required fields.
551
- * Make required field indicator optional and display legend when enabled.
552
- * Set default color option in wpColorPicker.
553
- * Small refactor to make more use of `get_template_variables`.
554
- * Button: Added field for `rel` attribute.
555
- * Maps: Added setting for global Google API key.
556
- * Small fix to allow checkboxes to act as 'conditional' state emitters.
557
- * Features: Change text form field to a tinymce field
558
- * Properly work with new Page Builder caching system
559
- * Ensure footer templates only printed when editing with Elementor.
560
- * Small IE8 fix
561
- * Contact: Prevent form fields from having 0px height if no height specified.
562
- * Fixed Google Maps info windows.
563
- * Image: Don't output empty attributes.
564
- * Don't attempt to load maps API if already loaded.
565
-
566
- = 1.8.2 - 1 April 2017 =
567
- * Compatibility with upcoming Page Builder 2.5 release.
568
- * Fixed compatibility with Elementor 1.4+.
569
- * Fixed incompatibility with Jetpack.
570
-
571
- = 1.8.1 - 3 February 2017 =
572
- * Fixed empty array warning.
573
- * Contact Form: Prevent empty title markup from being echoed.
574
- * Contact Form: Display email after name
575
- * Slider: Account for 0 speed.
576
- * Features: Fix sizing issue when using images instead of icons.
577
- * Use default unit if missing for measurement fields.
578
- * Price Table: Shortcode support for feature text.
579
- * Testimonial: Updated text radius label and fixed resulting functionality.
580
- * Revert change made to post search for link field.
581
- * Link Field: Make sure we have a valid post_types value.
582
-
583
- = 1.8 - 31 January 2017 =
584
- * Introduced compatibility system.
585
- * Added compatibility with Elementor and Beaver Builder.
586
- * Ensure radio inputs in repeaters have their checked property set correctly.
587
- * Various Call to Action widget improvements.
588
- * Use `text-align: center;` for features icons.
589
- * Always use HTTPS for Google Webfonts.
590
- * Post Selector: Exclude current post id
591
- * Post Selector: Add filter returned query
592
- * Post Carousel: Prevent empty title output.
593
- * Google Maps: Add ability to set link for Static Map.
594
- * Social Links: Add title field and title attributes for links.
595
- * Features: Add title text field for features
596
- * Button Widget: Add Font setting
597
- * Contact: Add radio field Type
598
- * Taxonomy: New Window Setting
599
- * Added a way of specifying post types for link field.
600
- * Introduced a global widget setup action.
601
-
602
- = 1.7.2 - 09 November 2016 =
603
- * Made fixes to pass PHP 7 compatibility checks.
604
- * Image Widget: Get alt and title text from chosen image.
605
- * Replaced markup parser with more actively maintained one.
606
- * Simple Masonry: ensure resize on load
607
- * Image Grid: Allow 0 as valid spacing value.
608
- * Editor Widget: Call `WP_Embed::run_shortcode` on Editor widget content
609
- * Maps: Added missing `typeof` causing maps api not to load properly.
610
- * Icon: Fixed URL output.
611
- * Fixed double slash in URLs.
612
- * Features: Use Measurement fields.
613
- * Apply modify_form to form arrays created in the constructor.
614
- * Contact Form: add email default email subject if no subject defined.
615
-
616
- = 1.7.1 - 21 September 2016 =
617
- * Fixed case of Maps widget in sidebar causing an error on pages without that sidebar.
618
- * Fixed icon field CSS.
619
-
620
- = 1.7 - 20 September 2016 =
621
- * Added mechanism for creating global widget setting.
622
- * Added mechanism for adding dismissible notices to widget forms.
623
- * Unified Google Maps JS working for maps widget and contact form location field.
624
- * Added icon search for icon field.
625
- * Added remove button to icon field.
626
- * Contact Form: Fixed clash with Firefox field validation.
627
- * Properly display remove button after importing Pixabay image.
628
-
629
- = 1.6.5 - 15 August 2016 =
630
- * Fixed dialog z-index.
631
- * Added field required argument.
632
- * Properly trigger change for image search import.
633
- * Sanitize arg can now be a callback.
634
- * Improved multi checkbox field
635
- * Maps: Just call initialization function if maps API already loaded.
636
-
637
- = 1.6.4 - 21 July 2016 =
638
- * More settings and customizability for Headline widget.
639
- * Added FitText to Headline and Hero Image widgets.
640
- * Fixed Pixabay image importing.
641
-
642
- = 1.6.3 - 19 July 2016 =
643
- * Added image search functionality to media field.
644
- * Moved actions into their own file.
645
- * Allow widgets to provide their own LESS/HTML.
646
- * Added very simple code field.
647
- * Multiple widgets can have the same class. Allowing widget functionality to come from configuration.
648
- * Various tweaks for upcoming Widgets Builder plugin.
649
-
650
- = 1.6.2 - 11 July 2016 =
651
- * Fixed Firefox issue in post selector builder.
652
- * Properly escape all uses off add_query_arg.
653
- * Added filter after video
654
-
655
- = 1.6.1 - 24 June 2016 =
656
- * Social Links: Fixed auto-filling of network colors.
657
- * Social Links: Added 500px network.
658
- * Social Links: Added title tag to link tags.
659
- * Maps: Prevent JS error in when maps widget script is enqueued but widget isn't displayed.
660
- * Maps: Made API field more prominent as it's now required by the Google Maps API.
661
- * Added more general error checking.
662
-
663
- = 1.6 - 21 June 2016 =
664
- * Added builder field.
665
- * Added new multi checkboxes field.
666
- * Added Layout Slider widget.
667
- * Added taxonomy widget.
668
- * Added slider wrapper attributes and filter.
669
- * Fix for measurement field inside a repeater.
670
- * Modified base folder to work independently of Widgets Bundle.
671
- * Added custom icon families callback argument to icon field.
672
- * Properly handle attachments in post selector
673
- * Contact Form: Refactored form fields.
674
- * Hero Image: Added image type to Hero Image widget.
675
- * Button: Handle empty width.
676
- * Image: Added filter for SiteOrigin image attributes.
677
- * Image: Add dimensions to sizes dropdown.
678
- * Maps: Ensure maps widget works with API key.
679
- * Hero Image: Added setting to disable swipe on mobile Hero Image Widget.
680
- * Fixed title syntax in Image widget.
681
- * Video: Correctly get video file mime-types.
682
- * Video Widget: Allow specifying multiple self-hosted video sources to support various formats.
683
-
684
- = 1.5.11 - April 11 2016 =
685
- * Fixed features widget container shape setting.
686
-
687
- = 1.5.10 - April 5 2016 =
688
- * Added Icon widget.
689
- * Moved widget form arrays into separate functions to improve performance.
690
- * Cache widget style CSS if it can't be saved to filesystem.
691
- * Improved preview checking so preview style CSS isn't stored.
692
- * Contact Form: Improved instance hashing for compatibility with Yoast SEO.
693
- * Contact Form: Added description field and customisation.
694
- * Slider: Ensure correct styles are applied to slider images when a link is defined.
695
- * Features: Allow user to select size for uploaded icon image.
696
- * Price Table: Ensure feature icons always vertically centered, alongside feature text.
697
-
698
- = 1.5.9 - February 26 2016 =
699
- * Contact Form: Fixed hash checking for duplicate emails.
700
- * Contact Form: Replace default emails with admin_email.
701
-
702
- = 1.5.8 - February 26 2016 =
703
- * Skip empty sidebars when loading widget scripts.
704
- * Changes to cache clearing.
705
- * Typo corrections.
706
- * Fixed conflict with Child Theme Configurator.
707
- * Image Grid widget: Using correct field and image size names to determine image sizes.
708
- * Editor widget: Added shortcode unautop to Editor widget.
709
- * Contact Form widget: Added check to prevent email resends in contact form widget.
710
- * Masonry widget: properly handles full width rows in Page Builder.
711
- * Hero Image widget: Fix backgrounds URL.
712
- * Price Table widget: Skip empty buttons.
713
- * Maps Widget: Allow clicking markers to reopen info windows if closed.
714
-
715
- = 1.5.7 - February 4 2016 =
716
- * Restored old class name for Image Grid Widget.
717
-
718
- = 1.5.6 - January 23 2016 =
719
- * Fixed widget name migration
720
- * Fixed hero image height issue.
721
- * Fixed admin page layout.
722
-
723
- = 1.5.5 - January 21 2016 =
724
- * Changed widget folder names to make them less verbose.
725
- * Properly handle LESS compile errors.
726
- * Fixed regex causing only the first 10 TinyMCE fields to be initialized.
727
- * Fixed sanitization in the contact form.
728
- * Fixed Google webfont function.
729
- * Fixed image output for slider base.
730
- * Image Widget: Added alignment options.
731
- * Contact Form: Use anchor to return to form after submit
732
- * Change default caps to manage options.
733
- * Contact form widget: fixed - form in customizer doesn't resize.
734
- * Price Table: Added image alt tags.
735
- * Editor Widget: Fixed issue where only admins can view unfiltered content.
736
- * Editor Widget: Fixed issue where Editor Widget was removing new lines in code.
737
- * Post Selector Field: Support for date fields.
738
- * Maps Widget: Fixed Lat/Long coordinate handling.
739
- * Masonry widget: fixed layout and sizing.
740
- * Image Widget: Allow display of image title above or below image.
741
- * Added more relative measurement units to base.
742
- * Hero Image Widget: Added height setting.
743
- * Testimonial widget: Prevent outputting related image HTML if no image is set.
744
- * Testimonial Widget: Use testimonial URLs to link location and optionally link names and images.
745
- * Contact Form: Prevent multiple submit button clicks.
746
- * Image Widget: Add support for srcset to Image widget
747
- * Contact Form: Allow user to set field label position.
748
- * Contact Form: Allow user to set field label font styles.
749
- * Contact Form: Allow user setting focussed field outline styles.
750
- * Contact Form: Don't do recaptcha validation in admin preview.
751
-
752
- = 1.5.4 - November 18 2015 =
753
- * Fixed compatibility with PHP 5.2
754
-
755
- = 1.5.3 - November 17 2015 =
756
- * Fixed defaults for Features widget and Hero Image widget.
757
- * Fixed previewing for Editor widget.
758
- * Change measurement field to work as single string.
759
- * Use new measurement field for existing widgets.
760
- * Carousel widget supports RTL.
761
-
762
- = 1.5.2 - November 10 2015 =
763
- * Removed word break style from headline widget.
764
- * Fixed image grid URL field.
765
- * Added more text styling options to features widget.
766
- * Added measurement field to use in various widgets.
767
- * Prefix function name in Google Map widget to prevent conflicts.
768
- * Fixed styling for contact form widget.
769
- * Fix to allow multiple duplicated contact forms on a single page.
770
- * Fixed Hero Image widget button shortcode in text mode.
771
- * TinyMCE fields maintain editor state.
772
- * Added support for WP Canvas Shortcodes in TinyMCE field.
773
- * Don't initialize TinyMCE outside the admin.
774
- * Added more styling to contact form submit button.
775
-
776
- = 1.5.1 - October 7 2015 =
777
- * Fixed: Issue with Call To Action widget being missing.
778
-
779
- = 1.5 - October 5 2015 =
780
- * Fixed: Conflict between WPML and repeaters.
781
- * Added Simple Masonry Layout widget.
782
- * Added Contact Form widget.
783
- * Added Image Grid widget.
784
- * Added Testimonial widget.
785
- * Changed layout of widgets activation page.
786
- * Added Trianglify to generate placeholder widget icons.
787
- * Added mechanism to use state emitters in repeaters.
788
- * Section expanded/collapsed states now stored across form loads.
789
- * Display once off admin notice when new widgets are available.
790
- * Fixed translation domain.
791
- * Editor Widget: Allow more HTML in Editor widget for trusted users.
792
- * Hero Image Widget: Added top padding setting.
793
- * Hero Image Widget: Can now set background click URL.
794
- * Hero Image Widget: Improved handling of buttons shortcode.
795
- * Slider Widget : Fixed open in new window setting.
796
- * Headline Widget: Added word-break CSS.
797
- * Headline Widget: Added option to set type of heading tags used.
798
-
799
- = 1.4.4 - September 6 2015 =
800
- * Fixed issue with slider image widths.
801
-
802
- = 1.4.3 - September 5 2015 =
803
- * Added support for WooCommerce Shortcodes plugin to TinyMCE field.
804
- * New streamlined icon selector field.
805
- * Added info window functionality to maps widget.
806
- * Added a button to duplicate repeater items.
807
- * Added more design settings to hero image widget.
808
- * Removed full screen mode from TinyMCE field.
809
- * Option to keep map centered when container is resized.
810
- * Fixed: CSS bug for Google font imports on generated CSS.
811
- * Fixed: Post selector for URL fields properly handles empty titles.
812
- * Added option to skip auto paragraphs in Editor widget.
813
-
814
- = 1.4.2 - August 18 2015 =
815
- * Urgent fix in preparation for WordPress 4.3 release
816
-
817
- = 1.4.1 - August 17 2015 =
818
- * Updated to latest Font Awesome.
819
- * Added TripAdvisor to social links widget.
820
- * Allow unfiltered HTML in SiteOrigin Editor Widget if user has rights.
821
- * Properly set URL scheme.
822
- * Fixed state emitter issue for Google Maps Widget.
823
-
824
- = 1.4 - July 20 2015 =
825
- * Created a base slider widget class.
826
- * Converted current slider widget to use base slider.
827
- * Fixed image sizing in slider widget.
828
- * Added plain background color option to slider widget.
829
- * Added new Hero Image widget.
830
- * Fixed repeaters in sub items.
831
-
832
- = 1.3.1 =
833
- * Fix to TinyMCE field when moved in Customizer and Widgets interface.
834
- * Small developer level improvements.
835
- * Fixed autoplay in video widget.
836
- * Fixed behaviour of slides in slider widget.
837
-
838
- = 1.3 =
839
- * Added TinyMCE field type.
840
- * All fields now use classes to make them easier to extend.
841
- * Added SiteOrigin Editor widget.
842
- * Made it possible for other plugins to filter default widgets.
843
- * Fixed WordPress CLI compatibility.
844
- * Added unit tests.
845
- * Added networks to social networks widget.
846
- * Changed how repeater HTML is stored.
847
-
848
- = 1.2.4 =
849
- * Fixed reference to siteorigin_widgets_is_google_webfont.
850
- * Fixed CSS URL.
851
-
852
- = 1.2.3 =
853
- * Fixed Javascript issue with Map widget in customizer.
854
- * Added meta box manager.
855
- * Small style change to flat button style.
856
- * Video widget fixes.
857
-
858
- = 1.2.2 =
859
- * Added video widget with support for self/external videos.
860
- * New activate/deactivate widgets interface.
861
- * Headline widget CSS fixes.
862
- * Dev Feature: Error checking for widget field type.
863
- * Dev Feature: Added state emitters.
864
- * Dev Feature: Additional hooks and filters.
865
-
866
- = 1.2.1 =
867
- * Removed is_customizer_preview - only available in newer versions of WordPress.
868
-
869
- = 1.2 =
870
- * Added headline widget.
871
- * All scripts and styles loaded in header instead of lazy loading.
872
- * Added email to social links widget.
873
- * Made carousel touch friendly.
874
- * Improved input sanitization for HTML input.
875
- * Added nonce request checking in carousel widget.
876
- * Added sticky field to post selector.
877
- * Added function to allow Page Builder to use post selector.
878
- * Added a few developer friendly filters.
879
- * Fixed: Various customizer related issues.
880
- * Fixed: Issue limiting maps widget to 10 markers.
881
- * Fixed: Call to action alignment issues.
882
- * Fixed: Carousel preview.
883
-
884
- = 1.1.2 =
885
- * Added social links widget.
886
- * Framework updates.
887
-
888
- = 1.1.1 =
889
- * Fixed Google Map preview.
890
-
891
- = 1.1 =
892
- * Added powerful Google Maps widget.
893
- * Improved data sanitization.
894
- * Various UI improvements.
895
-
896
- = 1.0.6 =
897
- * Fixed issues with adding extra widget folders.
898
- * Added compatibility with WordPress Customizer.
899
- * Added more fields to be used with future widgets.
900
-
901
- = 1.0.5 =
902
- * Removed legacy widget deactivation functions.
903
- * Improved how widgets are loaded.
904
-
905
- = 1.0.4 =
906
- * Changed how widget list is loaded to fix issue with widgets list not displaying.
907
-
908
- = 1.0.3 =
909
- * Features widget icons can now be made clickable.
910
-
911
- = 1.0.2 =
912
- * Manage widgets page now does live updates.
913
- * Added widget previews.
914
- * Fixed wire button widget hover issue.
915
- * Old stand alone widget plugins are now deactivated in favor of bundled versions.
916
- * Fixed centering of CTA widget.
917
- * Fixed color settings in CTA widget.
918
- * Fixed button icon color setting.
919
- * Small UI improvements.
920
-
921
- = 1.0.1 =
922
- * Clean up of code and bundled widgets.
923
-
924
- = 1.0 =
925
- * Initial release.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === SiteOrigin Widgets Bundle ===
2
+ Tags: bundle, widget, button, slider, image, carousel, price table, google maps, tinymce, social links
3
+ Requires at least: 4.2
4
+ Tested up to: 5.4
5
+ Stable tag: 1.16.1
6
+ Build time: 2020-04-20T15:41:44+02:00
7
+ License: GPLv3 or later
8
+ Contributors: gpriday, braam-genis
9
+ Donate link: https://siteorigin.com/downloads/premium/
10
+
11
+ The SiteOrigin Widgets Bundle gives you a collection of widgets that you can use and customize. All the widgets are built on our powerful framework, giving you advanced forms, unlimited colours and 1500+ icons.
12
+
13
+ == Description ==
14
+
15
+ The SiteOrigin Widgets Bundle gives you a collection of widgets that you can use and customize. All the widgets are built on our powerful framework, giving you advanced forms, unlimited colours and 1500+ icons.
16
+
17
+ Widgets are great. No matter where you’re using them. In a [Page Builder](http://siteorigin.com/page-builder/) page or on your widgetized areas. It's even compatible with other popular page building plugins.
18
+
19
+ [vimeo https://vimeo.com/102103379]
20
+
21
+ The collection is growing, but here’s what we have so far.
22
+
23
+ * Google Maps Widget that's going places.
24
+ * Button Widget that you’ll love to click.
25
+ * Image Widget that’ll let you add images everywhere.
26
+ * Call To Action Widget that’ll get your users performing the actions you want.
27
+ * Slider Widget that slides images and HTML5 videos.
28
+ * Price Table Widget that’ll help you sell more.
29
+ * Post Carousel Widget that displays your posts as a carousel.
30
+ * Features Widget that lets you display a set of site or service features.
31
+ * Video Widget to get your videos out there.
32
+ * Headline Widget to get you noticed.
33
+ * Social Media Buttons which link to all your social media profiles.
34
+ * Accordion Widget to compress your content.
35
+ * Contact Form Widget to let people know you care.
36
+ * Editor Widget let's you richly edit text anywhere.
37
+ * Hero Widget that'll save your site design.
38
+ * Icon Widget for when only icons will do.
39
+ * Image Grid Widget that'll let you add images everywhere... in a grid.
40
+ * Layout Slider Widget lets you build layouts on slides using SiteOrigin Page Builder.
41
+ * Masonry Widget to add images in a masonry layout.
42
+ * Tabs Widget that'll let you group content into tabbed sections.
43
+ * Taxonomy Widget to display the selected taxonomy for the current post.
44
+ * Testimonials Widget to show people what your users/customers think of you.
45
+
46
+ Once you enable a widget, you'll be able to use it anywhere standard widgets are used. You can manage your widgets by going to Plugins > SiteOrigin Widgets in your WordPress admin.
47
+
48
+ == Documentation ==
49
+
50
+ [Documentation](https://siteorigin.com/widgets-bundle/getting-started/) is available on SiteOrigin.
51
+
52
+ == Support ==
53
+
54
+ We offer free support on the [SiteOrigin support forums](https://siteorigin.com/thread/).
55
+
56
+ = Create Custom Widgets =
57
+
58
+ The SiteOrigin Widgets Bundle is the perfect platform to build widgets for your theme or plugin. Read more on our [developer docs](https://siteorigin.com/docs/widgets-bundle/).
59
+
60
+ == Screenshots ==
61
+
62
+ 1. Manage which widgets you want enabled or disabled.
63
+ 2. The button widget shows the clean, standard interface all the widgets use.
64
+ 3. An example of the button widget.
65
+
66
+ == Changelog ==
67
+
68
+ == 1.16.1 - 20 April 2020 ==
69
+ * Accordion: When hiding panels, only search the current accordion and not nested accordions.
70
+ * Slider Widgets: Removed slide navigation numbers from excerpt output.
71
+ * Added support for custom icon styles.
72
+ * Tabs: Fixed top/bottom tab alignment when tab position is set to right/left.
73
+ * Post Carousel: Prevent themes from adjusting the thumbnail top margin.
74
+ * Improved the reliability of widget description translations. Updated various widget descriptions.
75
+ * Editor: Resolved the notice appearing when post meta wasn't available.
76
+ * Simple Masonry: Item labels - If the item title field isn't populated use the image title field.
77
+ * Hero: Added a setting to vertically align the slide contents.
78
+ * Updated jQuery TouchSwipe.
79
+ * Sliders: Fixed pagination spacing when HTML optimization is in use.
80
+ * Layout Slider: Set frame labels based on the content inserted.
81
+ * Slider: Set frame labels based on the content inserted.
82
+ * Contact Form: Added placeholder support to the dropdown select field. Used if the field label position is set to Inside.
83
+ * Contact Form: Added Required support for the dropdown select field.
84
+ * FontAwesome: Moved Brands to the last position in dropdown list.
85
+ * Layout Slider: Added a setting to vertically align the slide contents.
86
+
87
+ = 1.16.0 - 11 February 2020 =
88
+ * Block Editor: Fixed widget select field width and alignment.
89
+ * Removed unused template files.
90
+ * Contact Form: Improved checking for SiteOrigin development email addresses.
91
+ * Minor styling improvements to the Classic and Block Editor admin interfaces.
92
+ * Features: Added a new setting to select the H tag to be used for the title field.
93
+ * Hero: If a height value is assigned, added prefilling to avoid a page jump.
94
+ * Hero: Added `font-display: swap` for Google font imports.
95
+ * Layout Slider: If a height value is assigned, added prefilling to avoid a page jump.
96
+ * Image Grid: Added a class of `sow-image-grid-image_html` to each image. Can be used to exclude images from Lazy Loading plugins.
97
+ * Simple Masonry: Added a class of `sow-masonry-grid-image` to each image. Can be used to exclude images from Lazy Loading plugins.
98
+ * Features: Added fallback support for the Icon image field.
99
+ * Testimonials: Add fallback support for the Image field.
100
+ * Post Carousel: Prevented looping until all posts are loaded.
101
+ * Post Carousel: Added a new setting to disable looping.
102
+ * Post Carousel: Prevented scrolling past loading items and loop as soon as last item is completely visible.
103
+ * Contact Form: Added disabled cursor to submit button when disabled.
104
+ * Block Editor: Resolved Features widget default settings.
105
+ * Tabs and Accordion: Account for accented characters.
106
+ * Social Media Buttons: Allowed for multiple instances of the same network without duplicating colors.
107
+ * Social Media Buttons: Ensured all icons are correctly centered.
108
+ * Contact Form: Added lightweight validation for phone numbers.
109
+ * Block Editor: Display author for third party widgets.
110
+ * Block Editor: Added processing for the more quicktag in the Editor widget.
111
+ * Tabs and Accordion: Added icon spacing.
112
+ * Testimonials: Improved image sizing behavior for square images.
113
+
114
+ = 1.15.9 - 11 November 2019 =
115
+ * Contact Form: Improved default email address handling.
116
+ * Contact Form: Improved subject field labeling.
117
+ * Post Carousel: Loop the carousel when reaching the end.
118
+ * Social Media Buttons: Fixed issue with responsive breakpoint unit of measurement.
119
+ * Google Maps: Ensured settings modal window opens when directed to insert API key.
120
+ * Google Maps: Fixed map center field when used in the Customizer.
121
+ * Fixed compatibility with WordPress 5.3.
122
+ * Minor code style and widget label improvements.
123
+
124
+ = 1.15.8 - 20 August 2019 =
125
+ * Run FitText setup on window resize events.
126
+ * TinyMCE field: Copy any missing content CSS urls from main editor.
127
+ * Post Carousel: Prevent scrolling past the last item.
128
+ * Contact Form: Prevent sending to testing/dev emails.
129
+ * Widget block: Add `h3` wrapper for widget titles.
130
+ * Image widget: Remove `width:inherit;` IE8 fix for bound setting which breaks in IE11.
131
+ * Sliders: Added padding to slider navigation arrows.
132
+ * Accordion: Check if if anchor is present in URL and scroll to Accordion item.
133
+ * Various form description and styling fixes.
134
+
135
+ = 1.15.7 - 22 May 2019 =
136
+ * Widget Block: Ensure changed data is retained after previewing.
137
+ * Image widget: Prevent overflow of image container when wrapped in link.
138
+ * Image Grid: Dispatch event to notify listeners that layout is complete.
139
+ * Image Grid: Fix layout for images wrapped in links.
140
+ * Image grid: Use image media title for display if title isn't set in the widget form.
141
+ * Layout Slider: Remove header and text style fields.
142
+ * Remove Autoptimize cache clearing as it detects changes automatically.
143
+ * Update FontAwesome icons.
144
+ * Google Maps location field: Ensure value is retained after preview in the block editor.
145
+ * Prevent issue in SiteOrigin Layout Block when `sowb` hasn't been defined.
146
+
147
+ = 1.15.6 - 29 April 2019 =
148
+ * Image: Fix images vertical stretching.
149
+ * Image: Fix widths for images wrapped in links.
150
+ * Google Maps Location Field: Remove some unnecessary use of jQuery to avoid `$ is not a function` errors.
151
+ * Google Maps Location Field: Check if matchError exists before accessing.
152
+
153
+ = 1.15.5 - 25 April 2019 =
154
+ * Removed admin notice for new widgets.
155
+ * Slider Base Widget: Removed unused background videos height setting.
156
+ * Price Table: Recalc equalized heights when window size or orientation changes.
157
+ * Google Maps location field: Use value in sanitization if already an array.
158
+ * Add compatibility for Autoptimize.
159
+ * Simple Masonry: Ensure all available width is used for layout.
160
+ * Image: Change alignment to use `display:flex` instead of `text-align`.
161
+
162
+ = 1.15.4 - 27 March 2019 =
163
+ * Slider field: Live updates for display value.
164
+ * Widget block: Show error if missing or invalid widget data.
165
+ * Google Maps: Add more links to relevant docs for enabling required APIs.
166
+ * Google Maps Location field: Catch API key errors and display notice.
167
+ * Run FitText resizer on `setup_widgets` too.
168
+ * Add font url as property of font info object.
169
+ * Image grid: Use opacity for initial hide of images so that size may still be detected.
170
+ * Google Maps: Detect draggable or scroll_zoom before running setting migration.
171
+ * Accordion and Tabs: Trigger window resize on start of animation.
172
+ * Icon: Prevent undefined index notices.
173
+
174
+ = 1.15.3 - 6 March 2019 =
175
+ * Image grid: Fallback support, alt text, use measurement fields.
176
+ * Features: Fix responsive layout.
177
+ * Google Maps: Update to use gesture handling and separate zoom level for mobile.
178
+ * Google Maps: Default height when height field is empty.
179
+ * Sliders: Option to always show navigation on mobile devices.
180
+ * Accordion: Keyboard navigation.
181
+ * Beaver Builder: Fix icons and widgets not saving.
182
+ * Video: Allow using YouTube embed URLs.
183
+ * Post Carousel: Accessibility improvements.
184
+ * Escape namespaced widgets in previews.
185
+ * Flag additional metaboxes as incompatible with the block editor.
186
+ * Fix state emitters for sub-widget fields.
187
+ * Google Maps: Remove API key field from widget form, in favor of global API key field.
188
+ * Google Maps: Display notice when API key missing.
189
+ * Contact form: Prevent double nonce.
190
+ * TinyMCE field: Prevent twemoji from replacing emoji in the textarea.
191
+ * Widget block: Show appropriate message when widget is missing or deactivated.
192
+ * Accordion: Fix open/close icon layout when set to left position.
193
+ * Social Media Buttons: Prevent the phone network from opening in a new window.
194
+ * Google Maps: Add map styles filter.
195
+ * Image radio field: New field created.
196
+ * Posts field: Option to specify allowed post types.
197
+ * Contact form: Add description to reCAPTCHA field specifying reCAPTCHA v2.
198
+
199
+ = 1.15.2 - 18 February 2019 =
200
+ * Tabs: Set default tab position to top.
201
+
202
+ = 1.15.1 - 15 February 2019 =
203
+ * Google maps: Use correct locations for static maps.
204
+
205
+ = 1.15.0 - 14 February 2019 =
206
+ * Location field: New specialized admin form field which autocompletes addresses using the Google Maps places library.
207
+ * Google maps: Moved global API key override to `modify_instance` to make key available in admin form too.
208
+ * Google maps: Auto-migration of locations to new location field format.
209
+ * Update LESS PHP library with fixes for PHP 7.3 compatibility.
210
+ * Features: Apply text styles to all features content, not just `<p>` tags.
211
+ * Social Media: New networks: Bandcamp, Goodreads, Telegram, Strava, Blogger.
212
+ * Accordion: Fix issue preventing use of numbers in panel titles.
213
+ * Block editor: Preview fixes.
214
+ * Beaver Builder compat: Fix widgets failing to update and CSS for FontAwesome icons.
215
+
216
+ = 1.14.1 - 9 January 2019 =
217
+ * Icon field: Set correct value of currently selected icon for non-FA icons.
218
+ * Icon field: Avoid requiring that third party icon families include a `filter.php` file.
219
+ * Widget block: Use JS array reduce function instead of lodash.
220
+ * Allow widgets registered by instance.
221
+ * Multi-measurement field: Fix layout.
222
+ * Block editor: Send widgetData when fetching widget forms.
223
+ * Tinymce field: Prevent JS console errors for hidden fields.
224
+ * Order field: Additional sanitization before rendering.
225
+
226
+ = 1.14.0 - 4 January 2019 =
227
+ * Accordion: allow multiple panels with the same title.
228
+ * Actions when widgets' CSS files are created/deleted.
229
+ * Compat fixes for PHP 7.3
230
+ * Indicate when 'setup_widgets' is triggered for previews.
231
+ * Accordion: Debounce window.location.hash updates to prevent incorrect states.
232
+ * Don't remove FitText window listener to ensure previously set up FitText elements still work.
233
+ * Icon field: Show loading indicator while icons are loading.
234
+ * Widget documentation links.
235
+ * Icons: Update to use latest FontAwesome icon sets.
236
+ * Sliders: Resize slides when widgets are set up.
237
+ * Elementor compat: Directly enqueue necessary scripts and styles for previews.
238
+ * Allow widget headers to be translated.
239
+ * Accordion: Keep the clicked panel in the viewport, if it moves out.
240
+ * TinyMCE field: Check if tinymce is available before using.
241
+
242
+ = 1.13.4 - 6 December 2018 =
243
+ * Widget block: Fix Layout Slider not being editable.
244
+ * Widget block: Correct used of i18n for block editor.
245
+ * Widget block: Fix previews.
246
+ * Google map: Move global API key override to `modify_instance` to ensure key is available in form.
247
+ * Widget block: Prevent multiple API requests.
248
+
249
+ = 1.13.3 - 15 November 2018 =
250
+ * Contact: Fix checkboxes and radio alignment on android.
251
+ * FitText: Set minimum font size to ensure readability.
252
+ * TinyMCE field: Use correct editor when block editor is present.
253
+ * Google maps: Use correct info window text for markers.
254
+ * TinyMCE: Remove 'editor-buttons' style enqueue causing conflicts.
255
+ * TinyMCE field: Prevent adding multiple copies of media buttons.
256
+ * Image widget: if no alt text is supplied add an empty alt attribute.
257
+ * Repeaters: Reverted some commits causing multiple issues.
258
+ * WP 5: Fixed some styles in the block editor.
259
+ * Only setup form fields in the dialog when a PB edit widget dialog is opened.
260
+ * Multi-measurement field: Fix autoFill in block editor and attempt to fix in PHP <= 5.3.
261
+
262
+ = 1.13.2 - 31 October 2018 =
263
+ * Builder field: Prevent error in PHP <= 5.4
264
+ * Avoid replacing repeater item id placeholders for child repeaters.
265
+ * Repeaters: In repeater setup, don't setup child repeaters.
266
+
267
+ = 1.13.1 - 29 October 2018 =
268
+ * Gutenberg: Alert user that changes will be lost when changing the widget type.
269
+ * Tabs: Keyboard navigation and more accessibility improvements.
270
+ * Google maps: Better geocoding request management.
271
+ * TinyMCE field: Use correct selector for checking whether click target is editor switching tab.
272
+ * Slider: Option to prevent hiding video on mobile.
273
+ * Accordion: Deep-linking for child accordions.
274
+ * Use inline CSS fallback if writing to file failed.
275
+ * Better FitText compressor description.
276
+ * Delete old widget styles when updating widgets.
277
+ * Layout Slider: Resoonsive height.
278
+ * Accordion: Expand when user is printing.
279
+ * Features: Text case adjustments and formatting.
280
+ * Beaver Builder: Dark styling.
281
+ * Builder field: Allow double-encoding to allow already encoded text in editors.
282
+ * Contact form: Prevent adding the anchor again if it's already been added.
283
+ * Contact form: Attempt to scroll to contact form after submitting, so result is visible.
284
+ * Builder field: Set data correctly from JS.
285
+ * Builder field: Don't encode already JSON encoded values.
286
+ * Gutenberg: Allow editing page containing deactivated widget.
287
+ * Gutenberg: Reset global `$post` after enqueueing widgets' scripts and styles, which might run secondary queries.
288
+
289
+ = 1.13.0 - 13 September 2018 =
290
+ * SiteOrigin Widgets Gutenberg block!
291
+ * Google Map: Prevent script from running further if no map canvas elements found.
292
+ * Removed style to set `p` margins to zero.
293
+ * Check that fallback image for static maps is not an empty string before attempting to use it.
294
+ * TinyMCE: Ensure target is one of the editor tabs when switching modes.
295
+ * Set values for repeaters which are direct children of section fields.
296
+ * Prevent unselected radio input state emitters from affecting form states, when form values are set programmatically.
297
+ * Plugin Action Links: Check if edit link is present before removal.
298
+ * Social Media Buttons: Added Phone and Angelist. Changed email title text.
299
+ * Metabox manager: Set empty post meta string value to array. Ensure metabox widget form values are saved when saving drafts too.
300
+
301
+ = 1.12.1 - 17 July 2018 =
302
+ * Contact: Allow non-string values in required field validation.
303
+ * Initialize CTA, Price Table and Video JS widgets correctly when in accordion/tabs widgets.
304
+
305
+ = 1.12.0 - 11 July 2018 =
306
+ * Contact: Add dedicated textarea height.
307
+ * Social Media Buttons: Adds WhatsApp social network.
308
+ * Features: Allow icon size to use a different unit of measurement.
309
+ * Repeater field: Update editor id in media buttons when duplicating item with TinyMCE editor.
310
+ * Posts field: taxonomy description.
311
+ * Price Table: Disable equalized row heights on mobile.
312
+ * Beaver Builder: Force icon fonts.
313
+ * Slider widgets: Added autoplay option for background videos.
314
+ * Maps: Renamed Google maps script to more sensible `sow.google-map.js`
315
+ * Editor: Prevent errors when visual editing is disabled for a user.
316
+ * Optimized images.
317
+ * Accordion/tabs: Trigger 'setup_widgets' to ensure any widgets in panels are initialized correctly.
318
+ * Contact: Use 'From' email address if there is no email field in the form.
319
+ * Hero: Filter out the align field in the button sub-widget form.
320
+ * Testimonials: Switch mobile and tablet resolution width field descriptions.
321
+ * Posts field: Allow clearing dates.
322
+ * Font field: Use correct value for 'Helvetica Neue' and added 'Arial' option.
323
+ * TA: Additional setting to allow clearing the default background colors.
324
+ * Contact: Allow a value of '0' for required fields and subject values.
325
+
326
+ = 1.11.8 - 12 April 2018 =
327
+ * Added action just before rendering widget previews.
328
+ * Editor: Removed `unwpautop`.
329
+ * Editor: Ensure TinyMCE field knows whether to apply `autop` or not.
330
+ * Editor: Only apply `autop` on display when using HTML editor.
331
+ * Editor: Prevent `widget_text` filters from running `do_shortcode`.
332
+
333
+ = 1.11.7 - 23 March 2018 =
334
+ * Image: Add title alignment setting.
335
+ * Button: Add max-width to ensure buttons are responsive.
336
+ * Hero: New filter for frame content 'siteorigin_hero_frame_content'
337
+ * Features: Don't set margin for one column left/right feature.
338
+ * Updated widget icons.
339
+ * Updated google web fonts.
340
+
341
+ = 1.11.6 - 14 March 2018 =
342
+ * Hero: Add responsive height settings.
343
+ * Added pikaday jQuery plugin and register pikaday scripts for front end too.
344
+ * Features: item float clearing and padding mobile specific.
345
+
346
+ = 1.11.5 - 13 March 2018 =
347
+ * Features: Better feature padding removal on row ends.
348
+ * Sliders: WCAG 2.4.4 compliance.
349
+ * Tabs: Hide widget title when no title is set.
350
+ * TinyMCE field: Added setting for `wpautop` processing which is on by default.
351
+ * Contact: When Gradient disabled, set basic background.
352
+ * Beaver Builder compat: Only set SOWB widget form values when editing a SOWB widget.
353
+ * Contact: Option to log submitter's IP address.
354
+ * Add random number and set `more_entropy` to increase chance of unique form ids.
355
+ * Contact: Added 'tel' field type which should show numeric keyboard on mobile.
356
+ * Media field: Trigger change event when removing selected image.
357
+ * Renamed the PHP LESS parser to `SiteOrigin_LessC` to avoid conflicts.
358
+ * Date range field: Prevent initializing date range fields multiple times and ensure date format consistent.
359
+ * Register pikaday as common script and enqueue as needed in fields.
360
+ * Google Map: Show satellite map type.
361
+ * Translation: Add context to From strings.
362
+ * Add missing semicolons to Ionicons codes.
363
+
364
+ = 1.11.4 - 7 February 2018 =
365
+ * Slider: Add playsinline for Video backgrounds for iOS.
366
+ * Repeater field: Trigger change events for repeater when adding, removing or duplicating items.
367
+ * TinyMCE field: Removed special handling for TinyMCE fields when retrieving data. Just use field value directly.
368
+ * Fixed build overwriting some CSS files.
369
+
370
+ = 1.11.3 - 10 January 2018 =
371
+ * Hero: Add margin-top to so-widget-sow-button for spacing.
372
+ * Accordion: Added overflow to prevent Image overlap.
373
+ * Google Maps: Always register Google Maps script.
374
+ * Social Buttons: Mobile Alignment global widget settings
375
+ * Contact Form: Ability to control the width of the submit button.
376
+ * Contact Form: Add alignment options for submit button.
377
+ * Contact Form: Setting submit button gradient intensity to 0 removes gradient.
378
+ * Contact Form: Add success and error hooks.
379
+ * Accordion: Don't output widget title if not set.
380
+ * Accordion: Icon title collapse fix.
381
+ * Contact Form: Add placeholder for field type input.
382
+ * Button: Icon placement setting.
383
+ * Hero: Adjustable Paragraph text shadow.
384
+ * Hero: Add font family setting for paragraphs.
385
+ * Hero: Add link color picker.
386
+ * Slider field: allow float values and allow specifying step size.
387
+ * Contact Form: Add ability to set onclick and id for submit button.
388
+ * Features: Add ability to control responsive breakpoint.
389
+ * Global Settings: Add support for global settings added by themes.
390
+ * Beaver Builder Compat: Don't enqueue assets when all widgets are deactivated.
391
+ * Hero: Text font empty check.
392
+ * Contact Form: Preserve existing location hash when contact form is submitted.
393
+ * Post Selector: Only include current post id in exclusion if singular.
394
+ * Copy correct radio values when duplicating repeater items.
395
+ * Checkbox field: Parse string value 'false' in checkbox field sanitization.
396
+
397
+ = 1.11.2 - 27 November 2017 =
398
+ * Fix compatibility with Beaver Builder Lite.
399
+ * Tabs: Recalculate height on resize.
400
+
401
+ = 1.11.1 - 24 November 2017 =
402
+ * Hero: Allow for shortcodes to work.
403
+ * Fix posts field not displaying selected values when multiple selected.
404
+ * Widgets Page: Fix missing icon issue on windows.
405
+ * Trigger 'hide' and 'show' events in Accordion and Tabs widgets when toggling content.
406
+ * Fix Google Maps widget not displaying when map is initially hidden.
407
+ * Fix Beaver Builder compatibility.
408
+ * Builder field: Pass builder type when setting up builder fields.
409
+ * Tabs: Use correct variable for tab anchor.
410
+ * Repeater field: Prevent radio inputs values being cleared in repeaters when sorting.
411
+ * Accordion: Added title field.
412
+ * Fix PHP version compatibility checker errors.
413
+
414
+ = 1.11.0 - 7 November 2017 =
415
+ * New Tabs widget!
416
+ * Contact: mention it's possible to send to multiple emails.
417
+ * Features: Fixes margin causing extended page.
418
+ * Presets field.
419
+ * Accordion: Add Repeater Label Title.
420
+ * Hero: ability to select an image size.
421
+ * TinyMCE field: Remember last selected editor.
422
+ * Add rel="noopener noreferrer" for all 3rd party/unknown links.
423
+ * Social Media Buttons Widget: comply WCAG 2.4.4
424
+
425
+ = 1.10.2 - 20 October 2017 =
426
+ * Fix for links sometimes not working in slider widgets.
427
+ * Fix multi-measurement field labels.
428
+
429
+ = 1.10.1 - 13 October 2017 =
430
+ * Fix subwidget fields initializion when not contained in a section.
431
+ * TinyMCE field: fix initialization in repeaters.
432
+
433
+ = 1.10.0 - 11 October 2017 =
434
+ * New Accordion widget!
435
+ * Prevent multiple initialization of media field.
436
+ * Use correct path for widget banner when defined in a theme.
437
+ * Video: Added option to show/hide related YouTube videos at end of video.
438
+ * Slider: Handle links inside slider frames first and then allow processing of frame background clicks.
439
+ * Give repeated fields in widget fields unique ids for state handling.
440
+ * New multi-measurement field.
441
+ * Widget Manager Path Comparison fix. (allows for settings to work)
442
+ * Button: Use `esc_js` instead of `esc_attr` for onclick.
443
+
444
+ = 1.9.10 - 14 September 2017 =
445
+ * TinyMCE field: fixed issue with filter for TinyMCE plugins.
446
+ * Added teaser messages for SiteOrigin Premium addons.
447
+
448
+ = 1.9.9 - 31 August 2017 =
449
+ * Avoid using relative paths in asset URLs.
450
+ * Fixed compat with latest Elementor update.
451
+
452
+ = 1.9.8 - 21 August 2017 =
453
+ * Use WordPress functions to exit AJAX actions.
454
+ * TinyMCE field: Initialized once.
455
+ * TinyMCE field: Simplified switching between TinyMCE and QuickTags.
456
+ * TinyMCE field: Check if individual TinyMCE settings are encoded as JSON and decode before re-encoding all settings.
457
+ * Some compat fixes for Elementor.
458
+ * TinyMCE field: Temporarily disable Jetpack Grunion editor.
459
+ * Use correct JS dependencies for Beaver Builder compatibility when `WP_DEBUG` not defined.
460
+ * Removed unnecessary enqueues in Beaver Builder compat for dashicons and wp media scripts.
461
+ * Post carousel: Only handle horizontal swipes.
462
+
463
+ = 1.9.7 - 11 August 2017 =
464
+ * Contact: Added user configurable field for 'From:' address.
465
+ * TinyMCE field: Use editor stylesheets for new TinyMCE editor.
466
+ * TinyMCE field: Use UTF-8 encoding for text output.
467
+ * Sliders: Check whether `$frames` is empty before using.
468
+ * Google Maps: Prevent automatic center for routes.
469
+
470
+ = 1.9.6 - 4 August 2017 =
471
+ * Slider: Background Video: Try embedding the video if oEmbed fails.
472
+ * Contact: Added some nonce checks.
473
+ * Contact: add reply-to header.
474
+ * Remove elementor panel width override.
475
+ * Editor: Fix TinyMCE editor button filters in WP >= 4.8.
476
+ * Editor: Preserve encoded HTML entities in TinyMCE field.
477
+ * TinyMCE field: Added missing `tiny_mce_before_init` filter.
478
+
479
+ = 1.9.5 - 25 July 2017 =
480
+ * Fixed icon field selection.
481
+ * TinyMCE field is initialized when quicktags is selected.
482
+ * Autocomplete field only initialized once.
483
+ * Posts field sanitization handles multiple post types.
484
+
485
+ = 1.9.4 - 24 July 2017 =
486
+ * Using new Editor JS API for TinyMCE field.
487
+ * Carousel: apply static position on `.overlay`.
488
+ * Layout Slider: Add ability to set Background image to Title and spaced the code.
489
+ * Add capabilities check to widget activation action.
490
+ * Testimonial: Corrected typo in description and corrected formatting.
491
+ * Enabling translation for "From:" in contact mail.
492
+
493
+ = 1.9.3 - 3 July 2017 =
494
+ * Editor: Fix settings form label.
495
+ * Don't select the external fallback field as value input.
496
+ * Social media buttons: Don't output calls when missing network name.
497
+ * Use gettext for widget global settings dialog title.
498
+ * Image: Added link attributes to template variables.
499
+ * Image grid: Use `get_template_variables`.
500
+ * Image grid: Template code structure a bit more readable.
501
+ * Simple masonry: Assign link attributes in `get_template_variables`.
502
+ * Slider widget: Output link attributes.
503
+ * Features: Remove redundant paragraph from template.
504
+ * Google Maps: Fix issue when no matches found in maps API error string.
505
+ * Google Maps: Mention required Google Maps APIs in field descriptions.
506
+ * Google Maps: Localized strings used in JS.
507
+ * Elementor 1.5: Ensure widgets' setup scripts are run after editing.
508
+
509
+ = 1.9.2 - 8 June 2017 =
510
+ * Post Carousel: default image for posts without featured images.
511
+ * Social Media Buttons: allow empty colors.
512
+ * Editor: prevent text processing for cache and post content rendering.
513
+ * Post selector field: Fix additional args encoding.
514
+ * Post selector field: Fix taxonomy search.
515
+
516
+ = 1.9.1 - 1 June 2017 =
517
+ * Fixed Maps widget JS error.
518
+
519
+ = 1.9 - 30 May 2017 =
520
+ * Compatibility with Visual Composer.
521
+ * Taxonomy widget text display.
522
+ * Price table widget: option to make feature row heights equal.
523
+ * New posts selector field based on other existing fields.
524
+ * New autocomplete field. Currently supports showing results from posts and taxonomies.
525
+ * New date-range field with option to select specific or relative dates.
526
+ * Editor widget: Global widget setting for default 'autop' state.
527
+ * Some layout fixes for widget forms in Elementor.
528
+ * Google Maps: fallback image when maps API not available or returns error.
529
+ * Contact form: Reduced intensity of disabled button styling.
530
+ * Google Maps: Fix markers not displaying when queries are rate limited.
531
+ * Features: Option to use specified icon size for custom icon images.
532
+ * Updated FontAwesome icon set to 4.7.0
533
+ * Updated IcoMoon icon set.
534
+ * Contact form: Allow duplicate forms on same page.
535
+ * Widget temp backup in browser storage.
536
+ * Google Maps: Custom marker icon for each marker.
537
+ * Option to specify default number of visible rows in icon field.
538
+ * Changed PHP LESS compiler to a better maintained version.
539
+
540
+ = 1.8.6 - 10 May 2017 =
541
+ * Editor widget supports Jetpack Markdown.
542
+ * Editor widget global setting for enabling/disabling 'autop' by default.
543
+ * Allow setting FitText compressor strength in hero and headline widgets.
544
+ * Fix variable name in `enqueue_registered_styles`.
545
+ * Fix FitText not working previews.
546
+
547
+ = 1.8.5 - 27 April 2017 =
548
+ * Fixed button hover class.
549
+
550
+ = 1.8.4 - 27 April 2017 =
551
+ * Fixed button URLs.
552
+ * Removed image `sizes` attribute when Jetpack Photon is enabled.
553
+ * Fixed missing widget handling for misnamed widgets.
554
+
555
+ = 1.8.3 - 26 April 2017 =
556
+ * Contact Form: Improved type Validation and added empty name check
557
+ * Contact Form: Add Field Design Settings
558
+ * Testimonial: Add responsive image sizes settings
559
+ * Added checks to prevent PHP warnings
560
+ * Improved handling of empty order fields.
561
+ * Small code refactoring in price table widget.
562
+ * Ensure all SiteOrigin widgets are grouped together in Page Builder.
563
+ * Slider: Remove slider sentinel contents to avoid things like duplicated video iframe for embedded videos
564
+ * Fix TinyMCE z-index.
565
+ * Headline: Fixed typo that tied subheadline new window to headline
566
+ * Ensure fittext is done before setting up hero slider.
567
+ * Ensure google font fields work in live editors/previews.
568
+ * Features: Allow specifying position of features widgets icons.
569
+ * Added * next to labels of required fields.
570
+ * Make required field indicator optional and display legend when enabled.
571
+ * Set default color option in wpColorPicker.
572
+ * Small refactor to make more use of `get_template_variables`.
573
+ * Button: Added field for `rel` attribute.
574
+ * Maps: Added setting for global Google API key.
575
+ * Small fix to allow checkboxes to act as 'conditional' state emitters.
576
+ * Features: Change text form field to a tinymce field
577
+ * Properly work with new Page Builder caching system
578
+ * Ensure footer templates only printed when editing with Elementor.
579
+ * Small IE8 fix
580
+ * Contact: Prevent form fields from having 0px height if no height specified.
581
+ * Fixed Google Maps info windows.
582
+ * Image: Don't output empty attributes.
583
+ * Don't attempt to load maps API if already loaded.
584
+
585
+ = 1.8.2 - 1 April 2017 =
586
+ * Compatibility with upcoming Page Builder 2.5 release.
587
+ * Fixed compatibility with Elementor 1.4+.
588
+ * Fixed incompatibility with Jetpack.
589
+
590
+ = 1.8.1 - 3 February 2017 =
591
+ * Fixed empty array warning.
592
+ * Contact Form: Prevent empty title markup from being echoed.
593
+ * Contact Form: Display email after name
594
+ * Slider: Account for 0 speed.
595
+ * Features: Fix sizing issue when using images instead of icons.
596
+ * Use default unit if missing for measurement fields.
597
+ * Price Table: Shortcode support for feature text.
598
+ * Testimonial: Updated text radius label and fixed resulting functionality.
599
+ * Revert change made to post search for link field.
600
+ * Link Field: Make sure we have a valid post_types value.
601
+
602
+ = 1.8 - 31 January 2017 =
603
+ * Introduced compatibility system.
604
+ * Added compatibility with Elementor and Beaver Builder.
605
+ * Ensure radio inputs in repeaters have their checked property set correctly.
606
+ * Various Call to Action widget improvements.
607
+ * Use `text-align: center;` for features icons.
608
+ * Always use HTTPS for Google Webfonts.
609
+ * Post Selector: Exclude current post id
610
+ * Post Selector: Add filter returned query
611
+ * Post Carousel: Prevent empty title output.
612
+ * Google Maps: Add ability to set link for Static Map.
613
+ * Social Links: Add title field and title attributes for links.
614
+ * Features: Add title text field for features
615
+ * Button Widget: Add Font setting
616
+ * Contact: Add radio field Type
617
+ * Taxonomy: New Window Setting
618
+ * Added a way of specifying post types for link field.
619
+ * Introduced a global widget setup action.
620
+
621
+ = 1.7.2 - 09 November 2016 =
622
+ * Made fixes to pass PHP 7 compatibility checks.
623
+ * Image Widget: Get alt and title text from chosen image.
624
+ * Replaced markup parser with more actively maintained one.
625
+ * Simple Masonry: ensure resize on load
626
+ * Image Grid: Allow 0 as valid spacing value.
627
+ * Editor Widget: Call `WP_Embed::run_shortcode` on Editor widget content
628
+ * Maps: Added missing `typeof` causing maps api not to load properly.
629
+ * Icon: Fixed URL output.
630
+ * Fixed double slash in URLs.
631
+ * Features: Use Measurement fields.
632
+ * Apply modify_form to form arrays created in the constructor.
633
+ * Contact Form: add email default email subject if no subject defined.
634
+
635
+ = 1.7.1 - 21 September 2016 =
636
+ * Fixed case of Maps widget in sidebar causing an error on pages without that sidebar.
637
+ * Fixed icon field CSS.
638
+
639
+ = 1.7 - 20 September 2016 =
640
+ * Added mechanism for creating global widget setting.
641
+ * Added mechanism for adding dismissible notices to widget forms.
642
+ * Unified Google Maps JS working for maps widget and contact form location field.
643
+ * Added icon search for icon field.
644
+ * Added remove button to icon field.
645
+ * Contact Form: Fixed clash with Firefox field validation.
646
+ * Properly display remove button after importing Pixabay image.
647
+
648
+ = 1.6.5 - 15 August 2016 =
649
+ * Fixed dialog z-index.
650
+ * Added field required argument.
651
+ * Properly trigger change for image search import.
652
+ * Sanitize arg can now be a callback.
653
+ * Improved multi checkbox field
654
+ * Maps: Just call initialization function if maps API already loaded.
655
+
656
+ = 1.6.4 - 21 July 2016 =
657
+ * More settings and customizability for Headline widget.
658
+ * Added FitText to Headline and Hero Image widgets.
659
+ * Fixed Pixabay image importing.
660
+
661
+ = 1.6.3 - 19 July 2016 =
662
+ * Added image search functionality to media field.
663
+ * Moved actions into their own file.
664
+ * Allow widgets to provide their own LESS/HTML.
665
+ * Added very simple code field.
666
+ * Multiple widgets can have the same class. Allowing widget functionality to come from configuration.
667
+ * Various tweaks for upcoming Widgets Builder plugin.
668
+
669
+ = 1.6.2 - 11 July 2016 =
670
+ * Fixed Firefox issue in post selector builder.
671
+ * Properly escape all uses off add_query_arg.
672
+ * Added filter after video
673
+
674
+ = 1.6.1 - 24 June 2016 =
675
+ * Social Links: Fixed auto-filling of network colors.
676
+ * Social Links: Added 500px network.
677
+ * Social Links: Added title tag to link tags.
678
+ * Maps: Prevent JS error in when maps widget script is enqueued but widget isn't displayed.
679
+ * Maps: Made API field more prominent as it's now required by the Google Maps API.
680
+ * Added more general error checking.
681
+
682
+ = 1.6 - 21 June 2016 =
683
+ * Added builder field.
684
+ * Added new multi checkboxes field.
685
+ * Added Layout Slider widget.
686
+ * Added taxonomy widget.
687
+ * Added slider wrapper attributes and filter.
688
+ * Fix for measurement field inside a repeater.
689
+ * Modified base folder to work independently of Widgets Bundle.
690
+ * Added custom icon families callback argument to icon field.
691
+ * Properly handle attachments in post selector
692
+ * Contact Form: Refactored form fields.
693
+ * Hero Image: Added image type to Hero Image widget.
694
+ * Button: Handle empty width.
695
+ * Image: Added filter for SiteOrigin image attributes.
696
+ * Image: Add dimensions to sizes dropdown.
697
+ * Maps: Ensure maps widget works with API key.
698
+ * Hero Image: Added setting to disable swipe on mobile Hero Image Widget.
699
+ * Fixed title syntax in Image widget.
700
+ * Video: Correctly get video file mime-types.
701
+ * Video Widget: Allow specifying multiple self-hosted video sources to support various formats.
702
+
703
+ = 1.5.11 - April 11 2016 =
704
+ * Fixed features widget container shape setting.
705
+
706
+ = 1.5.10 - April 5 2016 =
707
+ * Added Icon widget.
708
+ * Moved widget form arrays into separate functions to improve performance.
709
+ * Cache widget style CSS if it can't be saved to filesystem.
710
+ * Improved preview checking so preview style CSS isn't stored.
711
+ * Contact Form: Improved instance hashing for compatibility with Yoast SEO.
712
+ * Contact Form: Added description field and customisation.
713
+ * Slider: Ensure correct styles are applied to slider images when a link is defined.
714
+ * Features: Allow user to select size for uploaded icon image.
715
+ * Price Table: Ensure feature icons always vertically centered, alongside feature text.
716
+
717
+ = 1.5.9 - February 26 2016 =
718
+ * Contact Form: Fixed hash checking for duplicate emails.
719
+ * Contact Form: Replace default emails with admin_email.
720
+
721
+ = 1.5.8 - February 26 2016 =
722
+ * Skip empty sidebars when loading widget scripts.
723
+ * Changes to cache clearing.
724
+ * Typo corrections.
725
+ * Fixed conflict with Child Theme Configurator.
726
+ * Image Grid widget: Using correct field and image size names to determine image sizes.
727
+ * Editor widget: Added shortcode unautop to Editor widget.
728
+ * Contact Form widget: Added check to prevent email resends in contact form widget.
729
+ * Masonry widget: properly handles full width rows in Page Builder.
730
+ * Hero Image widget: Fix backgrounds URL.
731
+ * Price Table widget: Skip empty buttons.
732
+ * Maps Widget: Allow clicking markers to reopen info windows if closed.
733
+
734
+ = 1.5.7 - February 4 2016 =
735
+ * Restored old class name for Image Grid Widget.
736
+
737
+ = 1.5.6 - January 23 2016 =
738
+ * Fixed widget name migration
739
+ * Fixed hero image height issue.
740
+ * Fixed admin page layout.
741
+
742
+ = 1.5.5 - January 21 2016 =
743
+ * Changed widget folder names to make them less verbose.
744
+ * Properly handle LESS compile errors.
745
+ * Fixed regex causing only the first 10 TinyMCE fields to be initialized.
746
+ * Fixed sanitization in the contact form.
747
+ * Fixed Google webfont function.
748
+ * Fixed image output for slider base.
749
+ * Image Widget: Added alignment options.
750
+ * Contact Form: Use anchor to return to form after submit
751
+ * Change default caps to manage options.
752
+ * Contact form widget: fixed - form in customizer doesn't resize.
753
+ * Price Table: Added image alt tags.
754
+ * Editor Widget: Fixed issue where only admins can view unfiltered content.
755
+ * Editor Widget: Fixed issue where Editor Widget was removing new lines in code.
756
+ * Post Selector Field: Support for date fields.
757
+ * Maps Widget: Fixed Lat/Long coordinate handling.
758
+ * Masonry widget: fixed layout and sizing.
759
+ * Image Widget: Allow display of image title above or below image.
760
+ * Added more relative measurement units to base.
761
+ * Hero Image Widget: Added height setting.
762
+ * Testimonial widget: Prevent outputting related image HTML if no image is set.
763
+ * Testimonial Widget: Use testimonial URLs to link location and optionally link names and images.
764
+ * Contact Form: Prevent multiple submit button clicks.
765
+ * Image Widget: Add support for srcset to Image widget
766
+ * Contact Form: Allow user to set field label position.
767
+ * Contact Form: Allow user to set field label font styles.
768
+ * Contact Form: Allow user setting focussed field outline styles.
769
+ * Contact Form: Don't do recaptcha validation in admin preview.
770
+
771
+ = 1.5.4 - November 18 2015 =
772
+ * Fixed compatibility with PHP 5.2
773
+
774
+ = 1.5.3 - November 17 2015 =
775
+ * Fixed defaults for Features widget and Hero Image widget.
776
+ * Fixed previewing for Editor widget.
777
+ * Change measurement field to work as single string.
778
+ * Use new measurement field for existing widgets.
779
+ * Carousel widget supports RTL.
780
+
781
+ = 1.5.2 - November 10 2015 =
782
+ * Removed word break style from headline widget.
783
+ * Fixed image grid URL field.
784
+ * Added more text styling options to features widget.
785
+ * Added measurement field to use in various widgets.
786
+ * Prefix function name in Google Map widget to prevent conflicts.
787
+ * Fixed styling for contact form widget.
788
+ * Fix to allow multiple duplicated contact forms on a single page.
789
+ * Fixed Hero Image widget button shortcode in text mode.
790
+ * TinyMCE fields maintain editor state.
791
+ * Added support for WP Canvas Shortcodes in TinyMCE field.
792
+ * Don't initialize TinyMCE outside the admin.
793
+ * Added more styling to contact form submit button.
794
+
795
+ = 1.5.1 - October 7 2015 =
796
+ * Fixed: Issue with Call To Action widget being missing.
797
+
798
+ = 1.5 - October 5 2015 =
799
+ * Fixed: Conflict between WPML and repeaters.
800
+ * Added Simple Masonry Layout widget.
801
+ * Added Contact Form widget.
802
+ * Added Image Grid widget.
803
+ * Added Testimonial widget.
804
+ * Changed layout of widgets activation page.
805
+ * Added Trianglify to generate placeholder widget icons.
806
+ * Added mechanism to use state emitters in repeaters.
807
+ * Section expanded/collapsed states now stored across form loads.
808
+ * Display once off admin notice when new widgets are available.
809
+ * Fixed translation domain.
810
+ * Editor Widget: Allow more HTML in Editor widget for trusted users.
811
+ * Hero Image Widget: Added top padding setting.
812
+ * Hero Image Widget: Can now set background click URL.
813
+ * Hero Image Widget: Improved handling of buttons shortcode.
814
+ * Slider Widget : Fixed open in new window setting.
815
+ * Headline Widget: Added word-break CSS.
816
+ * Headline Widget: Added option to set type of heading tags used.
817
+
818
+ = 1.4.4 - September 6 2015 =
819
+ * Fixed issue with slider image widths.
820
+
821
+ = 1.4.3 - September 5 2015 =
822
+ * Added support for WooCommerce Shortcodes plugin to TinyMCE field.
823
+ * New streamlined icon selector field.
824
+ * Added info window functionality to maps widget.
825
+ * Added a button to duplicate repeater items.
826
+ * Added more design settings to hero image widget.
827
+ * Removed full screen mode from TinyMCE field.
828
+ * Option to keep map centered when container is resized.
829
+ * Fixed: CSS bug for Google font imports on generated CSS.
830
+ * Fixed: Post selector for URL fields properly handles empty titles.
831
+ * Added option to skip auto paragraphs in Editor widget.
832
+
833
+ = 1.4.2 - August 18 2015 =
834
+ * Urgent fix in preparation for WordPress 4.3 release
835
+
836
+ = 1.4.1 - August 17 2015 =
837
+ * Updated to latest Font Awesome.
838
+ * Added TripAdvisor to social links widget.
839
+ * Allow unfiltered HTML in SiteOrigin Editor Widget if user has rights.
840
+ * Properly set URL scheme.
841
+ * Fixed state emitter issue for Google Maps Widget.
842
+
843
+ = 1.4 - July 20 2015 =
844
+ * Created a base slider widget class.
845
+ * Converted current slider widget to use base slider.
846
+ * Fixed image sizing in slider widget.
847
+ * Added plain background color option to slider widget.
848
+ * Added new Hero Image widget.
849
+ * Fixed repeaters in sub items.
850
+
851
+ = 1.3.1 =
852
+ * Fix to TinyMCE field when moved in Customizer and Widgets interface.
853
+ * Small developer level improvements.
854
+ * Fixed autoplay in video widget.
855
+ * Fixed behaviour of slides in slider widget.
856
+
857
+ = 1.3 =
858
+ * Added TinyMCE field type.
859
+ * All fields now use classes to make them easier to extend.
860
+ * Added SiteOrigin Editor widget.
861
+ * Made it possible for other plugins to filter default widgets.
862
+ * Fixed WordPress CLI compatibility.
863
+ * Added unit tests.
864
+ * Added networks to social networks widget.
865
+ * Changed how repeater HTML is stored.
866
+
867
+ = 1.2.4 =
868
+ * Fixed reference to siteorigin_widgets_is_google_webfont.
869
+ * Fixed CSS URL.
870
+
871
+ = 1.2.3 =
872
+ * Fixed Javascript issue with Map widget in customizer.
873
+ * Added meta box manager.
874
+ * Small style change to flat button style.
875
+ * Video widget fixes.
876
+
877
+ = 1.2.2 =
878
+ * Added video widget with support for self/external videos.
879
+ * New activate/deactivate widgets interface.
880
+ * Headline widget CSS fixes.
881
+ * Dev Feature: Error checking for widget field type.
882
+ * Dev Feature: Added state emitters.
883
+ * Dev Feature: Additional hooks and filters.
884
+
885
+ = 1.2.1 =
886
+ * Removed is_customizer_preview - only available in newer versions of WordPress.
887
+
888
+ = 1.2 =
889
+ * Added headline widget.
890
+ * All scripts and styles loaded in header instead of lazy loading.
891
+ * Added email to social links widget.
892
+ * Made carousel touch friendly.
893
+ * Improved input sanitization for HTML input.
894
+ * Added nonce request checking in carousel widget.
895
+ * Added sticky field to post selector.
896
+ * Added function to allow Page Builder to use post selector.
897
+ * Added a few developer friendly filters.
898
+ * Fixed: Various customizer related issues.
899
+ * Fixed: Issue limiting maps widget to 10 markers.
900
+ * Fixed: Call to action alignment issues.
901
+ * Fixed: Carousel preview.
902
+
903
+ = 1.1.2 =
904
+ * Added social links widget.
905
+ * Framework updates.
906
+
907
+ = 1.1.1 =
908
+ * Fixed Google Map preview.
909
+
910
+ = 1.1 =
911
+ * Added powerful Google Maps widget.
912
+ * Improved data sanitization.
913
+ * Various UI improvements.
914
+
915
+ = 1.0.6 =
916
+ * Fixed issues with adding extra widget folders.
917
+ * Added compatibility with WordPress Customizer.
918
+ * Added more fields to be used with future widgets.
919
+
920
+ = 1.0.5 =
921
+ * Removed legacy widget deactivation functions.
922
+ * Improved how widgets are loaded.
923
+
924
+ = 1.0.4 =
925
+ * Changed how widget list is loaded to fix issue with widgets list not displaying.
926
+
927
+ = 1.0.3 =
928
+ * Features widget icons can now be made clickable.
929
+
930
+ = 1.0.2 =
931
+ * Manage widgets page now does live updates.
932
+ * Added widget previews.
933
+ * Fixed wire button widget hover issue.
934
+ * Old stand alone widget plugins are now deactivated in favor of bundled versions.
935
+ * Fixed centering of CTA widget.
936
+ * Fixed color settings in CTA widget.
937
+ * Fixed button icon color setting.
938
+ * Small UI improvements.
939
+
940
+ = 1.0.1 =
941
+ * Clean up of code and bundled widgets.
942
+
943
+ = 1.0 =
944
+ * Initial release.
so-widgets-bundle.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: SiteOrigin Widgets Bundle
4
  Description: A collection of all widgets, neatly bundled into a single plugin. It's also a framework to code your own widgets on top of.
5
- Version: 1.16.0
6
  Text Domain: so-widgets-bundle
7
  Domain Path: /lang
8
  Author: SiteOrigin
@@ -12,7 +12,7 @@ License: GPL3
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.txt
13
  */
14
 
15
- define('SOW_BUNDLE_VERSION', '1.16.0');
16
  define('SOW_BUNDLE_BASE_FILE', __FILE__);
17
 
18
  // Allow JS suffix to be pre-set
2
  /*
3
  Plugin Name: SiteOrigin Widgets Bundle
4
  Description: A collection of all widgets, neatly bundled into a single plugin. It's also a framework to code your own widgets on top of.
5
+ Version: 1.16.1
6
  Text Domain: so-widgets-bundle
7
  Domain Path: /lang
8
  Author: SiteOrigin
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.txt
13
  */
14
 
15
+ define('SOW_BUNDLE_VERSION', '1.16.1');
16
  define('SOW_BUNDLE_BASE_FILE', __FILE__);
17
 
18
  // Allow JS suffix to be pre-set
widgets/accordion/accordion.php CHANGED
@@ -14,7 +14,7 @@ class SiteOrigin_Widget_Accordion_Widget extends SiteOrigin_Widget {
14
  'sow-accordion',
15
  __( 'SiteOrigin Accordion', 'so-widgets-bundle' ),
16
  array(
17
- 'description' => __( 'An accordion widget.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/accordion-widget/',
19
  ),
20
  array(),
14
  'sow-accordion',
15
  __( 'SiteOrigin Accordion', 'so-widgets-bundle' ),
16
  array(
17
+ 'description' => __( 'An accordion to squeeze a lot of content into a small space.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/accordion-widget/',
19
  ),
20
  array(),
widgets/accordion/js/accordion.js CHANGED
@@ -12,7 +12,7 @@ jQuery( function ( $ ) {
12
  }
13
 
14
  var $accordionPanels = $( element ).find( '> .sow-accordion-panel' );
15
- $accordionPanels.not( '.sow-accordion-panel-open' ).find( '.sow-accordion-panel-content' ).hide();
16
  var openPanels = $accordionPanels.filter( '.sow-accordion-panel-open' ).toArray();
17
 
18
  var updateHash = function () {
12
  }
13
 
14
  var $accordionPanels = $( element ).find( '> .sow-accordion-panel' );
15
+ $accordionPanels.not( '.sow-accordion-panel-open' ).children( '.sow-accordion-panel-content' ).hide();
16
  var openPanels = $accordionPanels.filter( '.sow-accordion-panel-open' ).toArray();
17
 
18
  var updateHash = function () {
widgets/accordion/js/accordion.min.js CHANGED
@@ -1 +1 @@
1
- var sowb=window.sowb||{};jQuery((function(o){sowb.setupAccordion=function(){o(".sow-accordion").each((function(n,a){var e=o(this).closest(".so-widget-sow-accordion");if(e.data("initialized"))return o(this);var i=o(a).find("> .sow-accordion-panel");i.not(".sow-accordion-panel-open").find(".sow-accordion-panel-content").hide();var t=i.filter(".sow-accordion-panel-open").toArray(),c=function(){},r=function(n,a){var e=n.offset().top-90;a?o("body,html").animate({scrollTop:e},200):window.scrollTo(0,e)},s=function(n,a,e){var i=o(n);if(!i.is(".sow-accordion-panel-open")){i.find("> .sow-accordion-panel-content").slideDown({start:function(){o(window).trigger("resize"),o(sowb).trigger("setup_widgets")},complete:function(){e&&i.offset().top<window.scrollY&&r(i,!0),o(this).trigger("show")}}),i.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").attr("aria-expanded",!0),i.addClass("sow-accordion-panel-open"),t.push(n);var d=o(n).parents(".sow-accordion-panel");d.length&&!d.hasClass("sow-accordion-panel-open")&&s(d.get(0),!0),a||c()}},d=function(n,a){var e=o(n);e.is(".sow-accordion-panel-open")&&(e.find("> .sow-accordion-panel-content").slideUp((function(){o(this).trigger("hide")})),e.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").attr("aria-expanded",!1),e.removeClass("sow-accordion-panel-open"),t.splice(t.indexOf(n),1),a||c())};if(i.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").on("click keydown",(function(n){if("keydown"==n.type){if(13!==n.keyCode&&32!==n.keyCode)return;n.preventDefault()}var a=o(this),i=e.data("maxOpenPanels"),c=a.closest(".sow-accordion-panel");if(c.is(".sow-accordion-panel-open")?d(c.get(0)):s(c.get(0),!1,!0),!isNaN(i)&&i>0&&t.length>i){var r=0;o.each(t.reverse(),(function(o,n){r!==i?r++:d(t[o])}))}})),e.data("useAnchorTags")){var l;c=function(){l&&clearTimeout(l),l=setTimeout((function(){for(var n=[],a=o(".sow-accordion-panel-open").toArray(),e=0;e<a.length;e++){var i=o(a[e]).data("anchor");if(i){var t=o(a[e]).parents(".sow-accordion-panel");(!t.length||t.length&&t.hasClass("sow-accordion-panel-open"))&&(n[e]=i)}}n&&n.length?window.location.hash=n.join(","):window.location.hash&&window.history.pushState("",document.title,window.location.pathname+window.location.search)}),100)};var w=function(){for(var n=i.toArray(),a=0;a<n.length;a++){var e=n[a],t=o(e).data("anchor");window.location.hash.substring(1).split(",").some((function(o){return decodeURI(t)===decodeURI(o)}))?s(e,!0):d(e,!0)}};o(window).on("hashchange",w),window.location.hash?w():c();var p=e.data("initialScrollPanel");if(window.location.hash&&t.length)setTimeout((function(){r(o(t[0]))}),500);else if(p>0){var h=p>i.length?i.last():i.eq(p-1);setTimeout((function(){r(h)}),500)}}e.data("initialized",!0)}))},sowb.setupAccordion(),o(sowb).on("setup_widgets",sowb.setupAccordion)})),window.sowb=sowb;
1
+ var sowb=window.sowb||{};jQuery((function(o){sowb.setupAccordion=function(){o(".sow-accordion").each((function(n,e){var a=o(this).closest(".so-widget-sow-accordion");if(a.data("initialized"))return o(this);var i=o(e).find("> .sow-accordion-panel");i.not(".sow-accordion-panel-open").children(".sow-accordion-panel-content").hide();var t=i.filter(".sow-accordion-panel-open").toArray(),c=function(){},r=function(n,e){var a=n.offset().top-90;e?o("body,html").animate({scrollTop:a},200):window.scrollTo(0,a)},s=function(n,e,a){var i=o(n);if(!i.is(".sow-accordion-panel-open")){i.find("> .sow-accordion-panel-content").slideDown({start:function(){o(window).trigger("resize"),o(sowb).trigger("setup_widgets")},complete:function(){a&&i.offset().top<window.scrollY&&r(i,!0),o(this).trigger("show")}}),i.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").attr("aria-expanded",!0),i.addClass("sow-accordion-panel-open"),t.push(n);var d=o(n).parents(".sow-accordion-panel");d.length&&!d.hasClass("sow-accordion-panel-open")&&s(d.get(0),!0),e||c()}},d=function(n,e){var a=o(n);a.is(".sow-accordion-panel-open")&&(a.find("> .sow-accordion-panel-content").slideUp((function(){o(this).trigger("hide")})),a.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").attr("aria-expanded",!1),a.removeClass("sow-accordion-panel-open"),t.splice(t.indexOf(n),1),e||c())};if(i.find("> .sow-accordion-panel-header-container > .sow-accordion-panel-header").on("click keydown",(function(n){if("keydown"==n.type){if(13!==n.keyCode&&32!==n.keyCode)return;n.preventDefault()}var e=o(this),i=a.data("maxOpenPanels"),c=e.closest(".sow-accordion-panel");if(c.is(".sow-accordion-panel-open")?d(c.get(0)):s(c.get(0),!1,!0),!isNaN(i)&&i>0&&t.length>i){var r=0;o.each(t.reverse(),(function(o,n){r!==i?r++:d(t[o])}))}})),a.data("useAnchorTags")){var l;c=function(){l&&clearTimeout(l),l=setTimeout((function(){for(var n=[],e=o(".sow-accordion-panel-open").toArray(),a=0;a<e.length;a++){var i=o(e[a]).data("anchor");if(i){var t=o(e[a]).parents(".sow-accordion-panel");(!t.length||t.length&&t.hasClass("sow-accordion-panel-open"))&&(n[a]=i)}}n&&n.length?window.location.hash=n.join(","):window.location.hash&&window.history.pushState("",document.title,window.location.pathname+window.location.search)}),100)};var w=function(){for(var n=i.toArray(),e=0;e<n.length;e++){var a=n[e],t=o(a).data("anchor");window.location.hash.substring(1).split(",").some((function(o){return decodeURI(t)===decodeURI(o)}))?s(a,!0):d(a,!0)}};o(window).on("hashchange",w),window.location.hash?w():c();var p=a.data("initialScrollPanel");if(window.location.hash&&t.length)setTimeout((function(){r(o(t[0]))}),500);else if(p>0){var h=p>i.length?i.last():i.eq(p-1);setTimeout((function(){r(h)}),500)}}a.data("initialized",!0)}))},sowb.setupAccordion(),o(sowb).on("setup_widgets",sowb.setupAccordion)})),window.sowb=sowb;
widgets/button/button.php CHANGED
@@ -14,7 +14,7 @@ class SiteOrigin_Widget_Button_Widget extends SiteOrigin_Widget {
14
  'sow-button',
15
  __('SiteOrigin Button', 'so-widgets-bundle'),
16
  array(
17
- 'description' => __('A customizable button widget.', 'so-widgets-bundle'),
18
  'help' => 'https://siteorigin.com/widgets-bundle/button-widget-documentation/'
19
  ),
20
  array(
14
  'sow-button',
15
  __('SiteOrigin Button', 'so-widgets-bundle'),
16
  array(
17
+ 'description' => __('A powerful yet simple button widget for your sidebars or Page Builder pages.', 'so-widgets-bundle'),
18
  'help' => 'https://siteorigin.com/widgets-bundle/button-widget-documentation/'
19
  ),
20
  array(
widgets/contact/contact.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  /*
4
  Widget Name: Contact Form
5
- Description: A light weight contact form builder.
6
  Author: SiteOrigin
7
  Author URI: https://siteorigin.com
8
  Documentation: https://siteorigin.com/widgets-bundle/contact-form-widget/
@@ -16,7 +16,7 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
16
  'sow-contact-form',
17
  __( 'SiteOrigin Contact Form', 'so-widgets-bundle' ),
18
  array(
19
- 'description' => __( 'Create a simple contact form for your users to get hold of you.', 'so-widgets-bundle' ),
20
  ),
21
  array(),
22
  false,
@@ -932,9 +932,9 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
932
  if ( $indicate_required_fields && ! empty( $field['required']['required'] ) ) {
933
  $label .= '*';
934
  }
935
- $is_text_input_field = ( $field['type'] != 'select' && $field['type'] != 'radio' && $field['type'] != 'checkboxes' );
936
  // label should be rendered before the field, then CSS will do the exact positioning.
937
- $render_label_before_field = ( $label_position != 'below' && $label_position != 'inside' ) || ( $label_position == 'inside' && ! $is_text_input_field );
938
  if ( empty( $label_position ) || $render_label_before_field ) {
939
  $this->render_form_label( $field_id, $label, $label_position );
940
  }
2
 
3
  /*
4
  Widget Name: Contact Form
5
+ Description: A lightweight contact form builder.
6
  Author: SiteOrigin
7
  Author URI: https://siteorigin.com
8
  Documentation: https://siteorigin.com/widgets-bundle/contact-form-widget/
16
  'sow-contact-form',
17
  __( 'SiteOrigin Contact Form', 'so-widgets-bundle' ),
18
  array(
19
+ 'description' => __( 'A lightweight contact form builder.', 'so-widgets-bundle' ),
20
  ),
21
  array(),
22
  false,
932
  if ( $indicate_required_fields && ! empty( $field['required']['required'] ) ) {
933
  $label .= '*';
934
  }
935
+ $no_placeholder_support = ( $field['type'] != 'radio' && $field['type'] != 'checkboxes' );
936
  // label should be rendered before the field, then CSS will do the exact positioning.
937
+ $render_label_before_field = ( $label_position != 'below' && $label_position != 'inside' ) || ( $label_position == 'inside' && ! $no_placeholder_support );
938
  if ( empty( $label_position ) || $render_label_before_field ) {
939
  $this->render_form_label( $field_id, $label, $label_position );
940
  }
widgets/contact/fields/select.class.php CHANGED
@@ -5,7 +5,20 @@ class SiteOrigin_Widget_ContactForm_Field_Select extends SiteOrigin_Widget_Conta
5
  public function render_field( $options ) {
6
  ?><select name="<?php echo esc_attr( $options['field_name'] ) ?>"
7
  id="<?php echo esc_attr( $options['field_id'] ) ?>">
8
- <?php if ( ! empty( $options['field']['options'] ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  foreach ( $options['field']['options'] as $option ) { ?>
10
  <option
11
  value="<?php echo esc_attr( $option['value'] ) ?>"<?php echo selected( $option['value'], $options['value'], false ) ?>>
5
  public function render_field( $options ) {
6
  ?><select name="<?php echo esc_attr( $options['field_name'] ) ?>"
7
  id="<?php echo esc_attr( $options['field_id'] ) ?>">
8
+ <?php
9
+ if ( $options['show_placeholder'] ) {
10
+ ?>
11
+ <option selected disabled><?php esc_html_e( $options['field']['label'] ); ?></option>
12
+ <?php
13
+ }
14
+
15
+ if ( ! empty( $options['field']['options'] ) ) {
16
+ if ( ! $options['show_placeholder'] && $options['field']['required']['required'] ) {
17
+ ?>
18
+ <option selected <?php if ( ! $options['field']['required']['required'] ) echo 'disabled'; ?>></option>
19
+ <?php
20
+ }
21
+
22
  foreach ( $options['field']['options'] as $option ) { ?>
23
  <option
24
  value="<?php echo esc_attr( $option['value'] ) ?>"<?php echo selected( $option['value'], $options['value'], false ) ?>>
widgets/cta/cta.php CHANGED
@@ -15,7 +15,7 @@ class SiteOrigin_Widget_Cta_Widget extends SiteOrigin_Widget {
15
  'sow-cta',
16
  __('SiteOrigin Call-to-action', 'so-widgets-bundle'),
17
  array(
18
- 'description' => __('A simple call-to-action widget with massive power.', 'so-widgets-bundle'),
19
  'help' => 'https://siteorigin.com/widgets-bundle/call-action-widget/'
20
  ),
21
  array(
15
  'sow-cta',
16
  __('SiteOrigin Call-to-action', 'so-widgets-bundle'),
17
  array(
18
+ 'description' => __('A simple call-to-action widget. You can do what ever you want with a call-to-action widget.', 'so-widgets-bundle'),
19
  'help' => 'https://siteorigin.com/widgets-bundle/call-action-widget/'
20
  ),
21
  array(
widgets/editor/editor.php CHANGED
@@ -16,7 +16,7 @@ class SiteOrigin_Widget_Editor_Widget extends SiteOrigin_Widget {
16
  'sow-editor',
17
  __('SiteOrigin Editor', 'so-widgets-bundle'),
18
  array(
19
- 'description' => __('A rich-text, text editor.', 'so-widgets-bundle'),
20
  'help' => 'https://siteorigin.com/widgets-bundle/editor-widget/'
21
  ),
22
  array(),
@@ -115,7 +115,9 @@ class SiteOrigin_Widget_Editor_Widget extends SiteOrigin_Widget {
115
 
116
  private function process_more_quicktag( $content ) {
117
  $post = get_post();
118
- $panels_content = get_post_meta( $post->ID, 'panels_data', true );
 
 
119
  // We only want to do this processing if on archive pages for posts with non-PB layouts.
120
  if ( ! is_singular() && empty( $panels_content ) && ! $this->is_block_editor_page() && empty( $GLOBALS['SO_WIDGETS_BUNDLE_PREVIEW_RENDER'] ) ) {
121
  if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
16
  'sow-editor',
17
  __('SiteOrigin Editor', 'so-widgets-bundle'),
18
  array(
19
+ 'description' => __('A widget which allows editing of content using the TinyMCE editor.', 'so-widgets-bundle'),
20
  'help' => 'https://siteorigin.com/widgets-bundle/editor-widget/'
21
  ),
22
  array(),
115
 
116
  private function process_more_quicktag( $content ) {
117
  $post = get_post();
118
+ if ( ! empty( $post ) ) {
119
+ $panels_content = get_post_meta( $post->ID, 'panels_data', true );
120
+ }
121
  // We only want to do this processing if on archive pages for posts with non-PB layouts.
122
  if ( ! is_singular() && empty( $panels_content ) && ! $this->is_block_editor_page() && empty( $GLOBALS['SO_WIDGETS_BUNDLE_PREVIEW_RENDER'] ) ) {
123
  if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
widgets/features/features.php CHANGED
@@ -13,7 +13,7 @@ class SiteOrigin_Widget_Features_Widget extends SiteOrigin_Widget {
13
  'sow-features',
14
  __( 'SiteOrigin Features', 'so-widgets-bundle' ),
15
  array(
16
- 'description' => __( 'Displays a list of features.', 'so-widgets-bundle' ),
17
  'help' => 'https://siteorigin.com/widgets-bundle/features-widget-documentation/'
18
  ),
19
  array(),
13
  'sow-features',
14
  __( 'SiteOrigin Features', 'so-widgets-bundle' ),
15
  array(
16
+ 'description' => __( 'Displays a block of features with icons.', 'so-widgets-bundle' ),
17
  'help' => 'https://siteorigin.com/widgets-bundle/features-widget-documentation/'
18
  ),
19
  array(),
widgets/google-map/google-map.php CHANGED
@@ -16,7 +16,7 @@ class SiteOrigin_Widget_GoogleMap_Widget extends SiteOrigin_Widget {
16
  'sow-google-map',
17
  __( 'SiteOrigin Google Maps', 'so-widgets-bundle' ),
18
  array(
19
- 'description' => __( 'A Google Maps widget.', 'so-widgets-bundle' ),
20
  'help' => 'https://siteorigin.com/widgets-bundle/google-maps-widget/'
21
  ),
22
  array(),
16
  'sow-google-map',
17
  __( 'SiteOrigin Google Maps', 'so-widgets-bundle' ),
18
  array(
19
+ 'description' => __( 'A highly customisable Google Maps widget. Help your site find its place and give it some direction.', 'so-widgets-bundle' ),
20
  'help' => 'https://siteorigin.com/widgets-bundle/google-maps-widget/'
21
  ),
22
  array(),
widgets/headline/headline.php CHANGED
@@ -16,7 +16,7 @@ class SiteOrigin_Widget_Headline_Widget extends SiteOrigin_Widget {
16
  'sow-headline',
17
  __( 'SiteOrigin Headline', 'so-widgets-bundle' ),
18
  array(
19
- 'description' => __( 'A headline widget.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
16
  'sow-headline',
17
  __( 'SiteOrigin Headline', 'so-widgets-bundle' ),
18
  array(
19
+ 'description' => __( 'A headline to headline all headlines.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
widgets/hero/hero.php CHANGED
@@ -172,6 +172,12 @@ class SiteOrigin_Widget_Hero_Widget extends SiteOrigin_Widget_Base_Slider {
172
  'default' => 'default',
173
  ),
174
 
 
 
 
 
 
 
175
  'padding' => array(
176
  'type' => 'measurement',
177
  'label' => __('Top and bottom padding', 'so-widgets-bundle'),
@@ -401,6 +407,8 @@ class SiteOrigin_Widget_Hero_Widget extends SiteOrigin_Widget_Base_Slider {
401
  $less[ $key ] = $this->add_default_measurement_unit( $val );
402
  }
403
 
 
 
404
  $less['heading_shadow'] = intval( $instance['design']['heading_shadow'] );
405
  $less['heading_color'] = $instance['design']['heading_color'];
406
  $less['text_shadow'] = isset( $instance['design']['text_shadow'] ) ? floatval( $instance['design']['text_shadow'] ) : 0.25;
172
  'default' => 'default',
173
  ),
174
 
175
+ 'vertically_align' => array(
176
+ 'type' => 'checkbox',
177
+ 'label' => __( 'Vertically center align slide contents', 'so-widgets-bundle' ),
178
+ 'description' => __( 'For perfect centering, consider setting the Extra top padding setting to 0 when enabling this setting.', 'so-widgets-bundle' ),
179
+ ),
180
+
181
  'padding' => array(
182
  'type' => 'measurement',
183
  'label' => __('Top and bottom padding', 'so-widgets-bundle'),
407
  $less[ $key ] = $this->add_default_measurement_unit( $val );
408
  }
409
 
410
+ $less['vertically_align'] = empty( $instance['design']['vertically_align'] ) ? 'false' : 'true';
411
+
412
  $less['heading_shadow'] = intval( $instance['design']['heading_shadow'] );
413
  $less['heading_color'] = $instance['design']['heading_color'];
414
  $less['text_shadow'] = isset( $instance['design']['text_shadow'] ) ? floatval( $instance['design']['text_shadow'] ) : 0.25;
widgets/hero/styles/default.less CHANGED
@@ -27,6 +27,7 @@
27
 
28
  @responsive_breakpoint: 780px;
29
  @slide_height_responsive: default;
 
30
 
31
  // "Pre-fill" hero widget area if height is set
32
  & when ( isnumber( @slide_height ) ) {
@@ -55,6 +56,12 @@
55
  max-width: @slide_width;
56
  height: @slide_height;
57
 
 
 
 
 
 
 
58
  & when ( isnumber( @slide_height_responsive ) ) {
59
  @media (max-width: @responsive_breakpoint) {
60
  &{
27
 
28
  @responsive_breakpoint: 780px;
29
  @slide_height_responsive: default;
30
+ @vertically_align: false;
31
 
32
  // "Pre-fill" hero widget area if height is set
33
  & when ( isnumber( @slide_height ) ) {
56
  max-width: @slide_width;
57
  height: @slide_height;
58
 
59
+ & when (@vertically_align = true) {
60
+ display: flex;
61
+ flex-direction: column;
62
+ justify-content: center;
63
+ }
64
+
65
  & when ( isnumber( @slide_height_responsive ) ) {
66
  @media (max-width: @responsive_breakpoint) {
67
  &{
widgets/icon/icon.php CHANGED
@@ -16,7 +16,7 @@ class SiteOrigin_Widget_Icon_Widget extends SiteOrigin_Widget {
16
  'sow-icon',
17
  __( 'SiteOrigin Icon', 'so-widgets-bundle' ),
18
  array(
19
- 'description' => __( 'An icon widget.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
16
  'sow-icon',
17
  __( 'SiteOrigin Icon', 'so-widgets-bundle' ),
18
  array(
19
+ 'description' => __( 'An iconic icon.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
widgets/image-grid/image-grid.php CHANGED
@@ -20,7 +20,7 @@ class SiteOrigin_Widgets_ImageGrid_Widget extends SiteOrigin_Widget {
20
  'sow-image-grid',
21
  __('SiteOrigin Image Grid', 'so-widgets-bundle'),
22
  array(
23
- 'description' => __('Display a grid of images.', 'so-widgets-bundle'),
24
  ),
25
  array(),
26
  false,
20
  'sow-image-grid',
21
  __('SiteOrigin Image Grid', 'so-widgets-bundle'),
22
  array(
23
+ 'description' => __('Display a grid of images. Also useful for displaying client logos.', 'so-widgets-bundle'),
24
  ),
25
  array(),
26
  false,
widgets/image/image.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Widget Name: Image
4
- Description: A very simple image widget.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/image-widget-documentation/
1
  <?php
2
  /*
3
  Widget Name: Image
4
+ Description: A simple image widget with massive power.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/image-widget-documentation/
widgets/layout-slider/layout-slider.php CHANGED
@@ -36,9 +36,16 @@ class SiteOrigin_Widget_LayoutSlider_Widget extends SiteOrigin_Widget_Base_Slide
36
  'label' => __('Slider frames', 'so-widgets-bundle'),
37
  'item_name' => __('Frame', 'so-widgets-bundle'),
38
  'item_label' => array(
39
- 'selector' => "[id*='frames-title']",
40
- 'update_event' => 'change',
41
- 'value_method' => 'val'
 
 
 
 
 
 
 
42
  ),
43
 
44
  'fields' => array(
@@ -131,6 +138,12 @@ class SiteOrigin_Widget_LayoutSlider_Widget extends SiteOrigin_Widget_Base_Slide
131
  'label' => __( 'Responsive Height', 'so-widgets-bundle' ),
132
  ),
133
 
 
 
 
 
 
 
134
  'padding' => array(
135
  'type' => 'measurement',
136
  'label' => __('Top and bottom padding', 'so-widgets-bundle'),
@@ -315,6 +328,8 @@ class SiteOrigin_Widget_LayoutSlider_Widget extends SiteOrigin_Widget_Base_Slide
315
  $less[ $key ] = $this->add_default_measurement_unit( $val );
316
  }
317
 
 
 
318
  if ( ! empty( $instance['design']['heading_shadow'] ) ) {
319
  $less['heading_shadow'] = intval( $instance['design']['heading_shadow'] );
320
  }
36
  'label' => __('Slider frames', 'so-widgets-bundle'),
37
  'item_name' => __('Frame', 'so-widgets-bundle'),
38
  'item_label' => array(
39
+ 'selectorArray' => array(
40
+ array(
41
+ 'selector' => '.siteorigin-widget-field-image .media-field-wrapper .current .title',
42
+ 'valueMethod' => 'html'
43
+ ),
44
+ array(
45
+ 'selector' => '.siteorigin-widget-field-videos .siteorigin-widget-field-repeater-items .media-field-wrapper .current .title',
46
+ 'valueMethod' => 'html'
47
+ ),
48
+ ),
49
  ),
50
 
51
  'fields' => array(
138
  'label' => __( 'Responsive Height', 'so-widgets-bundle' ),
139
  ),
140
 
141
+ 'vertically_align' => array(
142
+ 'type' => 'checkbox',
143
+ 'label' => __( 'Vertically center align slide contents', 'so-widgets-bundle' ),
144
+ 'description' => __( 'For perfect centering, consider setting the Extra top padding setting to 0 when enabling this setting.', 'so-widgets-bundle' ),
145
+ ),
146
+
147
  'padding' => array(
148
  'type' => 'measurement',
149
  'label' => __('Top and bottom padding', 'so-widgets-bundle'),
328
  $less[ $key ] = $this->add_default_measurement_unit( $val );
329
  }
330
 
331
+ $less['vertically_align'] = empty( $instance['design']['vertically_align'] ) ? 'false' : 'true';
332
+
333
  if ( ! empty( $instance['design']['heading_shadow'] ) ) {
334
  $less['heading_shadow'] = intval( $instance['design']['heading_shadow'] );
335
  }
widgets/layout-slider/styles/default.less CHANGED
@@ -10,6 +10,7 @@
10
  @slide_height: default;
11
  @responsive_breakpoint: 780px;
12
  @slide_height_responsive: default;
 
13
 
14
  @text_size: default;
15
  @text_color: default;
@@ -42,6 +43,12 @@
42
 
43
  max-width: @slide_width;
44
  height: @slide_height;
 
 
 
 
 
 
45
 
46
  @media (max-width: @responsive_breakpoint) {
47
  // If no responsive height is set, remove slider height
10
  @slide_height: default;
11
  @responsive_breakpoint: 780px;
12
  @slide_height_responsive: default;
13
+ @vertically_align: false;
14
 
15
  @text_size: default;
16
  @text_color: default;
43
 
44
  max-width: @slide_width;
45
  height: @slide_height;
46
+
47
+ & when (@vertically_align = true) {
48
+ display: flex;
49
+ flex-direction: column;
50
+ justify-content: center;
51
+ }
52
 
53
  @media (max-width: @responsive_breakpoint) {
54
  // If no responsive height is set, remove slider height
widgets/post-carousel/css/style.css CHANGED
@@ -1 +1 @@
1
- @font-face{font-family:'carousel-arrows';src:url('fonts/carousel-arrows.eot?-95vnmw');src:url('fonts/carousel-arrows.eot?#iefix-95vnmw') format('embedded-opentype'),url('fonts/carousel-arrows.woff?-95vnmw') format('woff'),url('fonts/carousel-arrows.ttf?-95vnmw') format('truetype'),url('fonts/carousel-arrows.svg?-95vnmw#carousel-arrows') format('svg');font-weight:normal;font-style:normal}.sow-carousel-title .widget-title{display:inline-block;padding-right:15px}.sow-carousel-title a.sow-carousel-next,.sow-carousel-title a.sow-carousel-previous{font-family:'carousel-arrows';speak:none;display:block;float:right;overflow:hidden;margin-left:2px;margin-top:3px;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;font-size:8px;line-height:18px;width:18px;text-align:center;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;color:#FFFFFF;background:#333333;border-radius:2px}.sow-carousel-title a.sow-carousel-next:hover,.sow-carousel-title a.sow-carousel-previous:hover{background:#444444}.sow-carousel-title a.sow-carousel-next:before{content:"\e601"}.sow-carousel-title a.sow-carousel-previous:before{content:"\e600"}@media screen and (max-width:600px){.sow-carousel-title a.sow-carousel-previous{display:none}.sow-carousel-title a.sow-carousel-next{display:none}}.widget_sow-carousel{overflow-x:hidden;overflow-y:hidden}.sow-carousel-wrapper{overflow:hidden;position:relative;left:0;right:0}.sow-carousel-wrapper ul.sow-carousel-items{list-style:none;-webkit-transition:all .45s ease;-moz-transition:all .45s ease;-o-transition:all .45s ease;transition:all .45s ease;height:200px;margin:0;padding:0;zoom:1;width:99999px}.sow-carousel-wrapper ul.sow-carousel-items:before{content:'';display:block}.sow-carousel-wrapper ul.sow-carousel-items:after{content:'';display:table;clear:both}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item{list-style:none;margin-left:0;padding:0;display:block;float:left;margin-right:15px;overflow-x:hidden;overflow-y:hidden}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item:last-child{margin-right:0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item.rtl{float:right}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item.rtl:last-child{margin-right:15px}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail{line-height:0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a{display:block;background-position:center center}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a,.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a span.overlay{-webkit-transition:all .35s ease;-moz-transition:all .35s ease;-o-transition:all .35s ease;transition:all .35s ease}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a span.overlay{display:block;width:100%;height:100%;background:#3279BB;opacity:0;position:static}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a:hover span{opacity:.5}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-default-thumbnail{display:block;background:#E8E8E8;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #E0E0E0), color-stop(1, #E8E8E8));background:-ms-linear-gradient(bottom, #E0E0E0, #E8E8E8);background:-moz-linear-gradient(center bottom, #E0E0E0 0%, #E8E8E8 100%);background:-o-linear-gradient(#E8E8E8, #E0E0E0)}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item h3{font-size:15px;text-align:center;font-weight:500;color:#474747;margin:10px 0 0 0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item h3 a{text-decoration:none;color:inherit}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-loading{display:block;float:left;background:url(images/carousel-loader.gif) #F6F6F6 center center no-repeat;margin:0}a.sow-carousel-previous{display:none}a.sow-carousel-next{display:none}
1
+ @font-face{font-family:'carousel-arrows';src:url('fonts/carousel-arrows.eot?-95vnmw');src:url('fonts/carousel-arrows.eot?#iefix-95vnmw') format('embedded-opentype'),url('fonts/carousel-arrows.woff?-95vnmw') format('woff'),url('fonts/carousel-arrows.ttf?-95vnmw') format('truetype'),url('fonts/carousel-arrows.svg?-95vnmw#carousel-arrows') format('svg');font-weight:normal;font-style:normal}.sow-carousel-title .widget-title{display:inline-block;padding-right:15px}.sow-carousel-title a.sow-carousel-next,.sow-carousel-title a.sow-carousel-previous{font-family:'carousel-arrows';speak:none;display:block;float:right;overflow:hidden;margin-left:2px;margin-top:3px;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;font-size:8px;line-height:18px;width:18px;text-align:center;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;color:#FFFFFF;background:#333333;border-radius:2px}.sow-carousel-title a.sow-carousel-next:hover,.sow-carousel-title a.sow-carousel-previous:hover{background:#444444}.sow-carousel-title a.sow-carousel-next:before{content:"\e601"}.sow-carousel-title a.sow-carousel-previous:before{content:"\e600"}@media screen and (max-width:600px){.sow-carousel-title a.sow-carousel-previous{display:none}.sow-carousel-title a.sow-carousel-next{display:none}}.widget_sow-carousel{overflow-x:hidden;overflow-y:hidden}.sow-carousel-wrapper{overflow:hidden;position:relative;left:0;right:0}.sow-carousel-wrapper ul.sow-carousel-items{list-style:none;-webkit-transition:all .45s ease;-moz-transition:all .45s ease;-o-transition:all .45s ease;transition:all .45s ease;height:200px;margin:0;padding:0;zoom:1;width:99999px}.sow-carousel-wrapper ul.sow-carousel-items:before{content:'';display:block}.sow-carousel-wrapper ul.sow-carousel-items:after{content:'';display:table;clear:both}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item{list-style:none;margin-top:0;margin-left:0;padding:0;display:block;float:left;margin-right:15px;overflow-x:hidden;overflow-y:hidden}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item:last-child{margin-right:0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item.rtl{float:right}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item.rtl:last-child{margin-right:15px}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail{line-height:0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a{display:block;background-position:center center}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a,.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a span.overlay{-webkit-transition:all .35s ease;-moz-transition:all .35s ease;-o-transition:all .35s ease;transition:all .35s ease}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a span.overlay{display:block;width:100%;height:100%;background:#3279BB;opacity:0;position:static}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-thumbnail a:hover span{opacity:.5}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item .sow-carousel-default-thumbnail{display:block;background:#E8E8E8;background:-webkit-gradient(linear, left bottom, left top, color-stop(0, #E0E0E0), color-stop(1, #E8E8E8));background:-ms-linear-gradient(bottom, #E0E0E0, #E8E8E8);background:-moz-linear-gradient(center bottom, #E0E0E0 0%, #E8E8E8 100%);background:-o-linear-gradient(#E8E8E8, #E0E0E0)}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item h3{font-size:15px;text-align:center;font-weight:500;color:#474747;margin:10px 0 0 0}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-item h3 a{text-decoration:none;color:inherit}.sow-carousel-wrapper ul.sow-carousel-items li.sow-carousel-loading{display:block;float:left;background:url(images/carousel-loader.gif) #F6F6F6 center center no-repeat;margin:0}a.sow-carousel-previous{display:none}a.sow-carousel-next{display:none}
widgets/post-carousel/post-carousel.php CHANGED
@@ -49,7 +49,7 @@ class SiteOrigin_Widget_PostCarousel_Widget extends SiteOrigin_Widget {
49
  'sow-post-carousel',
50
  __('SiteOrigin Post Carousel', 'so-widgets-bundle'),
51
  array(
52
- 'description' => __('Display your posts as a carousel.', 'so-widgets-bundle'),
53
  'instance_storage' => true,
54
  'help' => 'https://siteorigin.com/widgets-bundle/post-carousel-widget/'
55
  ),
49
  'sow-post-carousel',
50
  __('SiteOrigin Post Carousel', 'so-widgets-bundle'),
51
  array(
52
+ 'description' => __('Gives you a widget to display your posts as a carousel.', 'so-widgets-bundle'),
53
  'instance_storage' => true,
54
  'help' => 'https://siteorigin.com/widgets-bundle/post-carousel-widget/'
55
  ),
widgets/price-table/price-table.php CHANGED
@@ -14,7 +14,7 @@ class SiteOrigin_Widget_PriceTable_Widget extends SiteOrigin_Widget {
14
  'sow-price-table',
15
  __( 'SiteOrigin Price Table', 'so-widgets-bundle' ),
16
  array(
17
- 'description' => __( 'A simple Price Table.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/price-table-widget/'
19
  ),
20
  array(),
14
  'sow-price-table',
15
  __( 'SiteOrigin Price Table', 'so-widgets-bundle' ),
16
  array(
17
+ 'description' => __( 'A powerful yet simple price table widget for your sidebars or Page Builder pages.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/price-table-widget/'
19
  ),
20
  array(),
widgets/simple-masonry/simple-masonry.php CHANGED
@@ -14,7 +14,7 @@ class SiteOrigin_Widget_Simple_Masonry_Widget extends SiteOrigin_Widget {
14
  'sow-simple-masonry',
15
  __('SiteOrigin Simple Masonry', 'so-widgets-bundle'),
16
  array(
17
- 'description' => __('A simple masonry layout widget.', 'so-widgets-bundle'),
18
  // 'help' => 'https://siteorigin.com/widgets-bundle/simple-masonry-widget-documentation/'
19
  ),
20
  array(),
@@ -47,7 +47,16 @@ class SiteOrigin_Widget_Simple_Masonry_Widget extends SiteOrigin_Widget {
47
  'type' => 'repeater',
48
  'label' => __( 'Images', 'so-widgets-bundle' ),
49
  'item_label' => array(
50
- 'selector' => "[id*='title']"
 
 
 
 
 
 
 
 
 
51
  ),
52
  'fields' => array(
53
  'image' => array(
14
  'sow-simple-masonry',
15
  __('SiteOrigin Simple Masonry', 'so-widgets-bundle'),
16
  array(
17
+ 'description' => __('A masonry layout for images. Images can link to your posts.', 'so-widgets-bundle'),
18
  // 'help' => 'https://siteorigin.com/widgets-bundle/simple-masonry-widget-documentation/'
19
  ),
20
  array(),
47
  'type' => 'repeater',
48
  'label' => __( 'Images', 'so-widgets-bundle' ),
49
  'item_label' => array(
50
+ 'selectorArray' => array(
51
+ array(
52
+ 'selector' => "[id*='title']",
53
+ 'valueMethod' => 'val',
54
+ ),
55
+ array(
56
+ 'selector' => '.media-field-wrapper .current .title',
57
+ 'valueMethod' => 'html'
58
+ ),
59
+ ),
60
  ),
61
  'fields' => array(
62
  'image' => array(
widgets/slider/slider.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Widget Name: Image Slider
4
- Description: A very simple slider widget.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/slider-widget-documentation/
@@ -34,9 +34,20 @@ class SiteOrigin_Widget_Slider_Widget extends SiteOrigin_Widget_Base_Slider {
34
  'label' => __('Slider frames', 'so-widgets-bundle'),
35
  'item_name' => __('Frame', 'so-widgets-bundle'),
36
  'item_label' => array(
37
- 'selector' => "[id*='frames-url']",
38
- 'update_event' => 'change',
39
- 'value_method' => 'val'
 
 
 
 
 
 
 
 
 
 
 
40
  ),
41
  'fields' => array(
42
  'background_videos' => array(
@@ -154,7 +165,8 @@ class SiteOrigin_Widget_Slider_Widget extends SiteOrigin_Widget_Base_Slider {
154
  echo siteorigin_widgets_get_attachment_image(
155
  $frame['foreground_image'],
156
  'full',
157
- !empty( $frame['foreground_image_fallback'] ) ? $frame['foreground_image_fallback'] : ''
 
158
  );
159
  ?>
160
  <?php if ( ! empty( $frame['url'] ) ) : ?>
@@ -180,7 +192,8 @@ class SiteOrigin_Widget_Slider_Widget extends SiteOrigin_Widget_Base_Slider {
180
  echo siteorigin_widgets_get_attachment_image(
181
  $frame['background_image'],
182
  'full',
183
- !empty( $frame['background_image_fallback'] ) ? $frame['background_image_fallback'] : ''
 
184
  );
185
 
186
  ?>
1
  <?php
2
  /*
3
  Widget Name: Image Slider
4
+ Description: A responsive slider widget that supports images and video.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/slider-widget-documentation/
34
  'label' => __('Slider frames', 'so-widgets-bundle'),
35
  'item_name' => __('Frame', 'so-widgets-bundle'),
36
  'item_label' => array(
37
+ 'selectorArray' => array(
38
+ array(
39
+ 'selector' => '.siteorigin-widget-field-background_image .media-field-wrapper .current .title',
40
+ 'valueMethod' => 'html'
41
+ ),
42
+ array(
43
+ 'selector' => '.siteorigin-widget-field-background_videos .siteorigin-widget-field-repeater-items .media-field-wrapper .current .title',
44
+ 'valueMethod' => 'html'
45
+ ),
46
+ array(
47
+ 'selector' => '.siteorigin-widget-field-foreground_image .media-field-wrapper .current .title',
48
+ 'valueMethod' => 'html'
49
+ ),
50
+ ),
51
  ),
52
  'fields' => array(
53
  'background_videos' => array(
165
  echo siteorigin_widgets_get_attachment_image(
166
  $frame['foreground_image'],
167
  'full',
168
+ !empty( $frame['foreground_image_fallback'] ) ? $frame['foreground_image_fallback'] : '',
169
+ array( 'class' => 'sow-slider-foreground-image' )
170
  );
171
  ?>
172
  <?php if ( ! empty( $frame['url'] ) ) : ?>
192
  echo siteorigin_widgets_get_attachment_image(
193
  $frame['background_image'],
194
  'full',
195
+ !empty( $frame['background_image_fallback'] ) ? $frame['background_image_fallback'] : '',
196
+ array( 'class' => 'sow-slider-background-image' )
197
  );
198
 
199
  ?>
widgets/social-media-buttons/social-media-buttons.php CHANGED
@@ -18,7 +18,7 @@ class SiteOrigin_Widget_SocialMediaButtons_Widget extends SiteOrigin_Widget {
18
  'sow-social-media-buttons',
19
  __( 'SiteOrigin Social Media Buttons', 'so-widgets-bundle' ),
20
  array(
21
- 'description' => __( 'A social media buttons widget.', 'so-widgets-bundle' )
22
  ),
23
  array(),
24
  false,
18
  'sow-social-media-buttons',
19
  __( 'SiteOrigin Social Media Buttons', 'so-widgets-bundle' ),
20
  array(
21
+ 'description' => __( 'Customizable buttons which link to all your social media profiles.', 'so-widgets-bundle' )
22
  ),
23
  array(),
24
  false,
widgets/tabs/styles/default.less CHANGED
@@ -43,29 +43,27 @@
43
  .sow-tabs-tab-container {
44
  background-color: @tabs_container_background_color;
45
  padding: @tabs_container_padding;
 
46
 
47
  & when ( @tabs_container_tabs_position = top ), ( @tabs_container_tabs_position = bottom ) {
48
- display: flex;
49
  flex-wrap: wrap;
50
  }
51
 
52
  & when ( @tabs_container_tabs_position = left ), ( @tabs_container_tabs_position = right ) {
53
- & when not ( @tabs_container_tabs_align = top ) {
54
- display: flex;
55
- flex-direction: column;
56
- & when ( @tabs_container_tabs_align = middle ) {
57
- justify-content: center;
58
- }
59
- & when ( @tabs_container_tabs_align = bottom ) {
60
- justify-content: flex-end;
61
- }
62
- }
63
  }
64
 
65
- & when ( @tabs_container_tabs_position = top ), ( @tabs_container_tabs_position = bottom ) {
66
- text-align: @tabs_container_tabs_align;
 
 
 
 
67
  }
68
 
 
 
 
69
 
70
  //noinspection CssOptimizeSimilarProperties
71
  & when ( @has_tabs_container_border_width = true ) {
43
  .sow-tabs-tab-container {
44
  background-color: @tabs_container_background_color;
45
  padding: @tabs_container_padding;
46
+ display: flex;
47
 
48
  & when ( @tabs_container_tabs_position = top ), ( @tabs_container_tabs_position = bottom ) {
 
49
  flex-wrap: wrap;
50
  }
51
 
52
  & when ( @tabs_container_tabs_position = left ), ( @tabs_container_tabs_position = right ) {
53
+ flex-direction: column;
 
 
 
 
 
 
 
 
 
54
  }
55
 
56
+ & when ( @tabs_container_tabs_align = middle ), ( @tabs_container_tabs_align = center ) {
57
+ justify-content: center;
58
+ }
59
+
60
+ & when ( @tabs_container_tabs_align = top ), ( @tabs_container_tabs_align = left ) {
61
+ align-items: flex-start;
62
  }
63
 
64
+ & when ( @tabs_container_tabs_align = bottom ), ( @tabs_container_tabs_align = right ) {
65
+ justify-content: flex-end;
66
+ }
67
 
68
  //noinspection CssOptimizeSimilarProperties
69
  & when ( @has_tabs_container_border_width = true ) {
widgets/tabs/tabs.php CHANGED
@@ -14,7 +14,7 @@ class SiteOrigin_Widget_Tabs_Widget extends SiteOrigin_Widget {
14
  'sow-tabs',
15
  __( 'SiteOrigin Tabs', 'so-widgets-bundle' ),
16
  array(
17
- 'description' => __( 'A tabs widget.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/tabs-widget/',
19
  ),
20
  array(),
14
  'sow-tabs',
15
  __( 'SiteOrigin Tabs', 'so-widgets-bundle' ),
16
  array(
17
+ 'description' => __( 'A tabby widget to switch between tabbed content panels.', 'so-widgets-bundle' ),
18
  'help' => 'https://siteorigin.com/widgets-bundle/tabs-widget/',
19
  ),
20
  array(),
widgets/taxonomy/taxonomy.php CHANGED
@@ -16,7 +16,7 @@ class SiteOrigin_Widget_Taxonomy_Widget extends SiteOrigin_Widget {
16
  'sow-taxonomy',
17
  __( 'SiteOrigin Taxonomy', 'so-widgets-bundle' ),
18
  array(
19
- 'description' => __( 'A taxonomy widget.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
16
  'sow-taxonomy',
17
  __( 'SiteOrigin Taxonomy', 'so-widgets-bundle' ),
18
  array(
19
+ 'description' => __( 'Displays the selected taxonomy for the current post.', 'so-widgets-bundle' )
20
  ),
21
  array(),
22
  false,
widgets/testimonial/testimonial.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  Widget Name: Testimonials
4
- Description: Display some testimonials.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/testimonials-widget/
@@ -14,7 +14,7 @@ class SiteOrigin_Widgets_Testimonials_Widget extends SiteOrigin_Widget {
14
  'sow-testimonials',
15
  __('SiteOrigin Testimonials', 'so-widgets-bundle'),
16
  array(
17
- 'description' => __('Share your product/service testimonials in a variety of different ways.', 'so-widgets-bundle'),
18
  'help' => 'https://siteorigin.com/widgets-bundle/testimonial-widget-documentation/'
19
  ),
20
  array(
1
  <?php
2
  /*
3
  Widget Name: Testimonials
4
+ Description: Share your product or service testimonials in a variety of different ways.
5
  Author: SiteOrigin
6
  Author URI: https://siteorigin.com
7
  Documentation: https://siteorigin.com/widgets-bundle/testimonials-widget/
14
  'sow-testimonials',
15
  __('SiteOrigin Testimonials', 'so-widgets-bundle'),
16
  array(
17
+ 'description' => __('Share your product or service testimonials in a variety of different ways.', 'so-widgets-bundle'),
18
  'help' => 'https://siteorigin.com/widgets-bundle/testimonial-widget-documentation/'
19
  ),
20
  array(
widgets/video/video.php CHANGED
@@ -17,7 +17,7 @@ class SiteOrigin_Widget_Video_Widget extends SiteOrigin_Widget {
17
  'sow-video',
18
  __( 'SiteOrigin Video Player', 'so-widgets-bundle' ),
19
  array(
20
- 'description' => __( 'A video player widget.', 'so-widgets-bundle' ),
21
  'help' => 'http://siteorigin.com/widgets-bundle/video-widget-documentation/'
22
  ),
23
  array(),
17
  'sow-video',
18
  __( 'SiteOrigin Video Player', 'so-widgets-bundle' ),
19
  array(
20
+ 'description' => __( 'Play all your self or externally hosted videos in a customizable video player.', 'so-widgets-bundle' ),
21
  'help' => 'http://siteorigin.com/widgets-bundle/video-widget-documentation/'
22
  ),
23
  array(),