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_\-,]+)\])?(\[\])?#x2F;))){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+#x2F;,"");var m=s.replace(/-\d+#x2F;,"");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+#x2F;)[0],a.find("label[for="+m+"]").attr("for",h)}else F=new RegExp("-\\d+quot;),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+") *quot;).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_\-,]+)\])?(\[\])?#x2F;))){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+#x2F;,"");var m=s.replace(/-\d+#x2F;,"");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+#x2F;)[0],a.find("label[for="+m+"]").attr("for",h)}else F=new RegExp("-\\d+quot;),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+") *quot;).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