SiteOrigin Widgets Bundle - Version 1.11.5

Version Description

  • 13 March 2018 =
  • Features: Better feature padding removal on row ends.
  • Sliders: WCAG 2.4.4 compliance.
  • Tabs: Hide widget title when no title is set.
  • TinyMCE field: Added setting for wpautop processing which is on by default.
  • Contact: When Gradient disabled, set basic background.
  • Beaver Builder compat: Only set SOWB widget form values when editing a SOWB widget.
  • Contact: Option to log submitter's IP address.
  • Add random number and set more_entropy to increase chance of unique form ids.
  • Contact: Added 'tel' field type which should show numeric keyboard on mobile.
  • Media field: Trigger change event when removing selected image.
  • Renamed the PHP LESS parser to SiteOrigin_LessC to avoid conflicts.
  • Date range field: Prevent initializing date range fields multiple times and ensure date format consistent.
  • Register pikaday as common script and enqueue as needed in fields.
  • Google Map: Show satellite map type.
  • Translation: Add context to From strings.
  • Add missing semicolons to Ionicons codes.
Download this release

Release Info

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

Code changes from version 1.11.4 to 1.11.5

base/inc/actions.php CHANGED
@@ -1,278 +1,278 @@
1
- <?php
2
-
3
- /**
4
- * Action for displaying the widget preview.
5
- */
6
- function siteorigin_widget_preview_widget_action() {
7
- if ( empty( $_REQUEST['_widgets_nonce'] ) ||
8
- ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
9
-
10
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
11
- } else if ( empty( $_POST['class'] ) ) {
12
- wp_die( __( 'Invalid post.', 'so-widgets-bundle' ), 400 );
13
- }
14
-
15
- // Get the widget from the widget factory
16
- global $wp_widget_factory;
17
- $widget = ! empty( $wp_widget_factory->widgets[ $_POST['class'] ] ) ? $wp_widget_factory->widgets[ $_POST['class'] ] : false;
18
-
19
- if( ! is_a( $widget, 'SiteOrigin_Widget' ) ) {
20
- wp_die( __( 'Invalid post.', 'so-widgets-bundle' ), 400 );
21
- }
22
-
23
- $instance = json_decode( stripslashes_deep($_POST['data']), true);
24
- /* @var $widget SiteOrigin_Widget */
25
- $instance = $widget->update( $instance, $instance );
26
- $instance['is_preview'] = true;
27
-
28
- // The theme stylesheet will change how the button looks
29
- wp_enqueue_style( 'theme-css', get_stylesheet_uri(), array(), rand( 0, 65536 ) );
30
- wp_enqueue_style( 'so-widget-preview', siteorigin_widgets_url( 'base/css/preview.css' ), array(), rand( 0,65536 ) );
31
-
32
- $sowb = SiteOrigin_Widgets_Bundle::single();
33
- $sowb->register_general_scripts();
34
-
35
- ob_start();
36
- $widget->widget( array(
37
- 'before_widget' => '',
38
- 'after_widget' => '',
39
- 'before_title' => '<h3 class="widget-title">',
40
- 'after_title' => '</h3>',
41
- ), $instance);
42
- $widget_html = ob_get_clean();
43
-
44
- // Print all the scripts and styles
45
- ?>
46
- <html>
47
- <head>
48
- <title><?php _e('Widget Preview', 'so-widgets-bundle') ?></title>
49
- <?php
50
- wp_print_scripts();
51
- wp_print_styles();
52
- siteorigin_widget_print_styles();
53
- ?>
54
- </head>
55
- <body>
56
- <?php // A lot of themes use entry-content as their main content wrapper ?>
57
- <div class="entry-content">
58
- <?php echo $widget_html ?>
59
- </div>
60
- </body>
61
- </html>
62
-
63
- <?php
64
- wp_die();
65
- }
66
- add_action('wp_ajax_so_widgets_preview', 'siteorigin_widget_preview_widget_action');
67
-
68
- /**
69
- * Action to handle searching posts
70
- */
71
- function siteorigin_widget_action_search_posts() {
72
- if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
73
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
74
- }
75
-
76
- // Get all public post types, besides attachments
77
- $post_types = (array) get_post_types( array(
78
- 'public' => true,
79
- ) );
80
-
81
- if ( ! empty( $_REQUEST['postTypes'] ) ) {
82
- $post_types = array_intersect( explode( ',', $_REQUEST['postTypes'] ), $post_types );
83
- } else {
84
- unset( $post_types['attachment'] );
85
- }
86
-
87
- $post_types = apply_filters( 'siteorigin_widgets_search_posts_post_types', $post_types );
88
-
89
- global $wpdb;
90
- if( !empty($_GET['query']) ) {
91
- $query = "AND post_title LIKE '%" . esc_sql( $_GET['query'] ) . "%'";
92
- }
93
- else {
94
- $query = '';
95
- }
96
-
97
- $post_types = "'" . implode("', '", array_map( 'esc_sql', $post_types ) ) . "'";
98
-
99
- $results = $wpdb->get_results( "
100
- SELECT ID AS 'value', post_title AS label, post_type AS 'type'
101
- FROM {$wpdb->posts}
102
- WHERE
103
- post_type IN ( {$post_types} ) AND post_status = 'publish' {$query}
104
- ORDER BY post_modified DESC
105
- LIMIT 20
106
- ", ARRAY_A );
107
-
108
- wp_send_json( apply_filters( 'siteorigin_widgets_search_posts_results', $results ) );
109
- }
110
- add_action('wp_ajax_so_widgets_search_posts', 'siteorigin_widget_action_search_posts');
111
-
112
- /**
113
- * Action to handle searching taxonomy terms.
114
- */
115
- function siteorigin_widget_action_search_terms() {
116
- if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
117
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
118
- }
119
-
120
- global $wpdb;
121
- $term = ! empty($_GET['term']) ? stripslashes($_GET['term']) : '';
122
- $term = trim($term, '%');
123
-
124
- $query = $wpdb->prepare("
125
- SELECT terms.term_id, terms.slug AS 'value', terms.name AS 'label', termtaxonomy.taxonomy AS 'type'
126
- FROM $wpdb->terms AS terms
127
- JOIN $wpdb->term_taxonomy AS termtaxonomy ON terms.term_id = termtaxonomy.term_id
128
- WHERE
129
- terms.name LIKE '%s'
130
- LIMIT 20
131
- ", '%' . esc_sql( $term ) . '%');
132
-
133
- $results = array();
134
-
135
- foreach ( $wpdb->get_results( $query ) as $result ) {
136
- $results[] = array(
137
- 'value' => $result->type . ':' . $result->value,
138
- 'label' => $result->label,
139
- 'type' => $result->type,
140
- );
141
- }
142
-
143
- wp_send_json( $results );
144
- }
145
- add_action('wp_ajax_so_widgets_search_terms', 'siteorigin_widget_action_search_terms');
146
-
147
- /**
148
- * Action for getting the number of posts returned by a query.
149
- */
150
- function siteorigin_widget_get_posts_count_action() {
151
-
152
- if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
153
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
154
- }
155
-
156
- $query = stripslashes( $_POST['query'] );
157
-
158
- wp_send_json( array( 'posts_count' => siteorigin_widget_post_selector_count_posts( $query ) ) );
159
- }
160
-
161
- add_action( 'wp_ajax_sow_get_posts_count', 'siteorigin_widget_get_posts_count_action' );
162
-
163
-
164
- function siteorigin_widget_remote_image_search(){
165
- if( empty( $_GET[ '_sononce' ] ) || ! wp_verify_nonce( $_GET[ '_sononce' ], 'so-image' ) ) {
166
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
167
- }
168
-
169
- if( empty( $_GET['q'] ) ) {
170
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 400 );
171
- }
172
-
173
- // Send the query to stock search server
174
- $url = add_query_arg( array(
175
- 'q' => $_GET[ 'q' ],
176
- 'page' => !empty( $_GET[ 'page' ] ) ? intval( $_GET[ 'page' ] ) : 1,
177
- ), 'http://stock.siteorigin.com/wp-admin/admin-ajax.php?action=image_search' );
178
-
179
- $result = wp_remote_get( $url, array(
180
- 'timeout' => 20,
181
- ) );
182
-
183
- if( ! is_wp_error( $result ) ) {
184
- $result = json_decode( $result['body'], true );
185
- if( !empty( $result['items'] ) ) {
186
- foreach( $result['items'] as & $r ) {
187
- if( !empty( $r['full_url'] ) ) {
188
- $r['import_signature'] = md5( $r['full_url'] . '::' . NONCE_SALT );
189
- }
190
- }
191
- }
192
- wp_send_json( $result );
193
- }
194
- else {
195
- $result = array(
196
- 'error' => true,
197
- 'message' => $result->get_error_message()
198
- );
199
- wp_send_json_error( $result );
200
- }
201
-
202
- }
203
- add_action('wp_ajax_so_widgets_image_search', 'siteorigin_widget_remote_image_search');
204
-
205
- function siteorigin_widget_image_import(){
206
- if( empty( $_GET[ '_sononce' ] ) || ! wp_verify_nonce( $_GET[ '_sononce' ], 'so-image' ) ) {
207
- $result = array(
208
- 'error' => true,
209
- 'message' => __( 'Nonce error', 'so-widgets-bundle' ),
210
- );
211
- }
212
- else if(
213
- empty( $_GET['import_signature'] ) ||
214
- empty( $_GET['full_url'] ) ||
215
- md5( $_GET['full_url'] . '::' . NONCE_SALT ) !== $_GET['import_signature']
216
- ) {
217
- $result = array(
218
- 'error' => true,
219
- 'message' => __( 'Signature error', 'so-widgets-bundle' ),
220
- );
221
- }
222
- else {
223
- // Fetch the image
224
- $src = media_sideload_image( $_GET['full_url'], $_GET['post_id'], null, 'src' );
225
- if( is_wp_error( $src ) ) {
226
- $result = array(
227
- 'error' => true,
228
- 'message' => $src->get_error_code(),
229
- );
230
- }
231
- else {
232
- global $wpdb;
233
- $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid='%s';", $src ) );
234
- if( !empty( $attachment ) ) {
235
- $thumb_src = wp_get_attachment_image_src( $attachment[0], 'thumbnail' );
236
- $result = array(
237
- 'error' => false,
238
- 'attachment_id' => $attachment[0],
239
- 'thumb' => $thumb_src[0]
240
- );
241
- }
242
- else {
243
- $result = array(
244
- 'error' => true,
245
- 'message' => __( 'Attachment error', 'so-widgets-bundle' ),
246
- );
247
- }
248
- }
249
- }
250
-
251
- // Return the result
252
- wp_send_json( $result );
253
- }
254
- add_action('wp_ajax_so_widgets_image_import', 'siteorigin_widget_image_import');
255
-
256
- /**
257
- * Action to handle a user dismissing a teaser notice.
258
- */
259
- function siteorigin_widgets_dismiss_widget_action(){
260
- if( empty( $_GET[ '_wpnonce' ] ) || ! wp_verify_nonce( $_GET[ '_wpnonce' ], 'dismiss-widget-teaser' ) ) {
261
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
262
- }
263
- if( empty( $_GET[ 'widget' ] ) ) {
264
- wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 400 );
265
- }
266
-
267
- $dismissed = get_user_meta( get_current_user_id(), 'teasers_dismissed', true );
268
- if( empty( $dismissed ) ) {
269
- $dismissed = array();
270
- }
271
-
272
- $dismissed[ $_GET[ 'widget' ] ] = true;
273
-
274
- update_user_meta( get_current_user_id(), 'teasers_dismissed', $dismissed );
275
-
276
- wp_die();
277
- }
278
- add_action( 'wp_ajax_so_dismiss_widget_teaser', 'siteorigin_widgets_dismiss_widget_action' );
1
+ <?php
2
+
3
+ /**
4
+ * Action for displaying the widget preview.
5
+ */
6
+ function siteorigin_widget_preview_widget_action() {
7
+ if ( empty( $_REQUEST['_widgets_nonce'] ) ||
8
+ ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
9
+
10
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
11
+ } else if ( empty( $_POST['class'] ) ) {
12
+ wp_die( __( 'Invalid post.', 'so-widgets-bundle' ), 400 );
13
+ }
14
+
15
+ // Get the widget from the widget factory
16
+ global $wp_widget_factory;
17
+ $widget = ! empty( $wp_widget_factory->widgets[ $_POST['class'] ] ) ? $wp_widget_factory->widgets[ $_POST['class'] ] : false;
18
+
19
+ if( ! is_a( $widget, 'SiteOrigin_Widget' ) ) {
20
+ wp_die( __( 'Invalid post.', 'so-widgets-bundle' ), 400 );
21
+ }
22
+
23
+ $instance = json_decode( stripslashes_deep($_POST['data']), true);
24
+ /* @var $widget SiteOrigin_Widget */
25
+ $instance = $widget->update( $instance, $instance );
26
+ $instance['is_preview'] = true;
27
+
28
+ // The theme stylesheet will change how the button looks
29
+ wp_enqueue_style( 'theme-css', get_stylesheet_uri(), array(), rand( 0, 65536 ) );
30
+ wp_enqueue_style( 'so-widget-preview', siteorigin_widgets_url( 'base/css/preview.css' ), array(), rand( 0,65536 ) );
31
+
32
+ $sowb = SiteOrigin_Widgets_Bundle::single();
33
+ $sowb->register_general_scripts();
34
+
35
+ ob_start();
36
+ $widget->widget( array(
37
+ 'before_widget' => '',
38
+ 'after_widget' => '',
39
+ 'before_title' => '<h3 class="widget-title">',
40
+ 'after_title' => '</h3>',
41
+ ), $instance);
42
+ $widget_html = ob_get_clean();
43
+
44
+ // Print all the scripts and styles
45
+ ?>
46
+ <html>
47
+ <head>
48
+ <title><?php _e('Widget Preview', 'so-widgets-bundle') ?></title>
49
+ <?php
50
+ wp_print_scripts();
51
+ wp_print_styles();
52
+ siteorigin_widget_print_styles();
53
+ ?>
54
+ </head>
55
+ <body>
56
+ <?php // A lot of themes use entry-content as their main content wrapper ?>
57
+ <div class="entry-content">
58
+ <?php echo $widget_html ?>
59
+ </div>
60
+ </body>
61
+ </html>
62
+
63
+ <?php
64
+ wp_die();
65
+ }
66
+ add_action('wp_ajax_so_widgets_preview', 'siteorigin_widget_preview_widget_action');
67
+
68
+ /**
69
+ * Action to handle searching posts
70
+ */
71
+ function siteorigin_widget_action_search_posts() {
72
+ if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
73
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
74
+ }
75
+
76
+ // Get all public post types, besides attachments
77
+ $post_types = (array) get_post_types( array(
78
+ 'public' => true,
79
+ ) );
80
+
81
+ if ( ! empty( $_REQUEST['postTypes'] ) ) {
82
+ $post_types = array_intersect( explode( ',', $_REQUEST['postTypes'] ), $post_types );
83
+ } else {
84
+ unset( $post_types['attachment'] );
85
+ }
86
+
87
+ $post_types = apply_filters( 'siteorigin_widgets_search_posts_post_types', $post_types );
88
+
89
+ global $wpdb;
90
+ if( !empty($_GET['query']) ) {
91
+ $query = "AND post_title LIKE '%" . esc_sql( $_GET['query'] ) . "%'";
92
+ }
93
+ else {
94
+ $query = '';
95
+ }
96
+
97
+ $post_types = "'" . implode("', '", array_map( 'esc_sql', $post_types ) ) . "'";
98
+
99
+ $results = $wpdb->get_results( "
100
+ SELECT ID AS 'value', post_title AS label, post_type AS 'type'
101
+ FROM {$wpdb->posts}
102
+ WHERE
103
+ post_type IN ( {$post_types} ) AND post_status = 'publish' {$query}
104
+ ORDER BY post_modified DESC
105
+ LIMIT 20
106
+ ", ARRAY_A );
107
+
108
+ wp_send_json( apply_filters( 'siteorigin_widgets_search_posts_results', $results ) );
109
+ }
110
+ add_action('wp_ajax_so_widgets_search_posts', 'siteorigin_widget_action_search_posts');
111
+
112
+ /**
113
+ * Action to handle searching taxonomy terms.
114
+ */
115
+ function siteorigin_widget_action_search_terms() {
116
+ if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
117
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
118
+ }
119
+
120
+ global $wpdb;
121
+ $term = ! empty($_GET['term']) ? stripslashes($_GET['term']) : '';
122
+ $term = trim($term, '%');
123
+
124
+ $query = $wpdb->prepare("
125
+ SELECT terms.term_id, terms.slug AS 'value', terms.name AS 'label', termtaxonomy.taxonomy AS 'type'
126
+ FROM $wpdb->terms AS terms
127
+ JOIN $wpdb->term_taxonomy AS termtaxonomy ON terms.term_id = termtaxonomy.term_id
128
+ WHERE
129
+ terms.name LIKE '%s'
130
+ LIMIT 20
131
+ ", '%' . esc_sql( $term ) . '%');
132
+
133
+ $results = array();
134
+
135
+ foreach ( $wpdb->get_results( $query ) as $result ) {
136
+ $results[] = array(
137
+ 'value' => $result->type . ':' . $result->value,
138
+ 'label' => $result->label,
139
+ 'type' => $result->type,
140
+ );
141
+ }
142
+
143
+ wp_send_json( $results );
144
+ }
145
+ add_action('wp_ajax_so_widgets_search_terms', 'siteorigin_widget_action_search_terms');
146
+
147
+ /**
148
+ * Action for getting the number of posts returned by a query.
149
+ */
150
+ function siteorigin_widget_get_posts_count_action() {
151
+
152
+ if ( empty( $_REQUEST['_widgets_nonce'] ) || ! wp_verify_nonce( $_REQUEST['_widgets_nonce'], 'widgets_action' ) ) {
153
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
154
+ }
155
+
156
+ $query = stripslashes( $_POST['query'] );
157
+
158
+ wp_send_json( array( 'posts_count' => siteorigin_widget_post_selector_count_posts( $query ) ) );
159
+ }
160
+
161
+ add_action( 'wp_ajax_sow_get_posts_count', 'siteorigin_widget_get_posts_count_action' );
162
+
163
+
164
+ function siteorigin_widget_remote_image_search(){
165
+ if( empty( $_GET[ '_sononce' ] ) || ! wp_verify_nonce( $_GET[ '_sononce' ], 'so-image' ) ) {
166
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
167
+ }
168
+
169
+ if( empty( $_GET['q'] ) ) {
170
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 400 );
171
+ }
172
+
173
+ // Send the query to stock search server
174
+ $url = add_query_arg( array(
175
+ 'q' => $_GET[ 'q' ],
176
+ 'page' => !empty( $_GET[ 'page' ] ) ? intval( $_GET[ 'page' ] ) : 1,
177
+ ), 'http://stock.siteorigin.com/wp-admin/admin-ajax.php?action=image_search' );
178
+
179
+ $result = wp_remote_get( $url, array(
180
+ 'timeout' => 20,
181
+ ) );
182
+
183
+ if( ! is_wp_error( $result ) ) {
184
+ $result = json_decode( $result['body'], true );
185
+ if( !empty( $result['items'] ) ) {
186
+ foreach( $result['items'] as & $r ) {
187
+ if( !empty( $r['full_url'] ) ) {
188
+ $r['import_signature'] = md5( $r['full_url'] . '::' . NONCE_SALT );
189
+ }
190
+ }
191
+ }
192
+ wp_send_json( $result );
193
+ }
194
+ else {
195
+ $result = array(
196
+ 'error' => true,
197
+ 'message' => $result->get_error_message()
198
+ );
199
+ wp_send_json_error( $result );
200
+ }
201
+
202
+ }
203
+ add_action('wp_ajax_so_widgets_image_search', 'siteorigin_widget_remote_image_search');
204
+
205
+ function siteorigin_widget_image_import(){
206
+ if( empty( $_GET[ '_sononce' ] ) || ! wp_verify_nonce( $_GET[ '_sononce' ], 'so-image' ) ) {
207
+ $result = array(
208
+ 'error' => true,
209
+ 'message' => __( 'Nonce error', 'so-widgets-bundle' ),
210
+ );
211
+ }
212
+ else if(
213
+ empty( $_GET['import_signature'] ) ||
214
+ empty( $_GET['full_url'] ) ||
215
+ md5( $_GET['full_url'] . '::' . NONCE_SALT ) !== $_GET['import_signature']
216
+ ) {
217
+ $result = array(
218
+ 'error' => true,
219
+ 'message' => __( 'Signature error', 'so-widgets-bundle' ),
220
+ );
221
+ }
222
+ else {
223
+ // Fetch the image
224
+ $src = media_sideload_image( $_GET['full_url'], $_GET['post_id'], null, 'src' );
225
+ if( is_wp_error( $src ) ) {
226
+ $result = array(
227
+ 'error' => true,
228
+ 'message' => $src->get_error_code(),
229
+ );
230
+ }
231
+ else {
232
+ global $wpdb;
233
+ $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid='%s';", $src ) );
234
+ if( !empty( $attachment ) ) {
235
+ $thumb_src = wp_get_attachment_image_src( $attachment[0], 'thumbnail' );
236
+ $result = array(
237
+ 'error' => false,
238
+ 'attachment_id' => $attachment[0],
239
+ 'thumb' => $thumb_src[0]
240
+ );
241
+ }
242
+ else {
243
+ $result = array(
244
+ 'error' => true,
245
+ 'message' => __( 'Attachment error', 'so-widgets-bundle' ),
246
+ );
247
+ }
248
+ }
249
+ }
250
+
251
+ // Return the result
252
+ wp_send_json( $result );
253
+ }
254
+ add_action('wp_ajax_so_widgets_image_import', 'siteorigin_widget_image_import');
255
+
256
+ /**
257
+ * Action to handle a user dismissing a teaser notice.
258
+ */
259
+ function siteorigin_widgets_dismiss_widget_action(){
260
+ if( empty( $_GET[ '_wpnonce' ] ) || ! wp_verify_nonce( $_GET[ '_wpnonce' ], 'dismiss-widget-teaser' ) ) {
261
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 403 );
262
+ }
263
+ if( empty( $_GET[ 'widget' ] ) ) {
264
+ wp_die( __( 'Invalid request.', 'so-widgets-bundle' ), 400 );
265
+ }
266
+
267
+ $dismissed = get_user_meta( get_current_user_id(), 'teasers_dismissed', true );
268
+ if( empty( $dismissed ) ) {
269
+ $dismissed = array();
270
+ }
271
+
272
+ $dismissed[ $_GET[ 'widget' ] ] = true;
273
+
274
+ update_user_meta( get_current_user_id(), 'teasers_dismissed', $dismissed );
275
+
276
+ wp_die();
277
+ }
278
+ add_action( 'wp_ajax_so_dismiss_widget_teaser', 'siteorigin_widgets_dismiss_widget_action' );
base/inc/fields/date-range.class.php CHANGED
@@ -1,123 +1,131 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Widget_Field_Date_Range
5
- */
6
- class SiteOrigin_Widget_Field_Date_Range extends SiteOrigin_Widget_Field_Base {
7
-
8
- /**
9
- * Either 'relative' or 'specific'. Whether to allow relative or specific date selection.
10
- *
11
- * @access protected
12
- * @var array
13
- */
14
- protected $date_type;
15
-
16
- protected function render_field( $value, $instance ) {
17
-
18
- if ( $this->date_type == 'specific' ) {
19
- $this->render_specific_date_selector();
20
- } else {
21
- $this->render_relative_date_selector( $value );
22
- }
23
- ?><input type="hidden"
24
- class="siteorigin-widget-input"
25
- value="<?php echo esc_attr( $value ) ?>"
26
- name="<?php echo esc_attr( $this->element_name ) ?>" /><?php
27
- }
28
-
29
- private function render_specific_date_selector() {
30
- ?><div class="sowb-specific-date-after"><span><?php
31
- _e( 'From', 'so-widgets-bundle' );
32
- ?></span><input type="text" class="datepicker after-picker"/></div><?php
33
- ?><div class="sowb-specific-date-before"><span><?php
34
- _e( 'to', 'so-widgets-bundle' );
35
- ?></span><input type="text" class="datepicker before-picker"/></div><?php
36
- }
37
-
38
- private function render_relative_date_selector( $value ) {
39
- $value = json_decode(
40
- $value,
41
- true
42
- );
43
-
44
- $from = ! empty( $value['from'] ) ? $value['from'] : array();
45
- $this->render_relative_date_selector_part( 'from', __( 'From', 'so-widgets-bundle' ), $from );
46
-
47
- $to = ! empty( $value['to'] ) ? $value['to'] : array();
48
- $this->render_relative_date_selector_part( 'to', __( 'to', 'so-widgets-bundle' ), $to );
49
- }
50
-
51
- private function render_relative_date_selector_part( $name, $label, $value ) {
52
- $units = $this->get_units();
53
-
54
- $val = ! empty( $value['value'] ) ? $value['value'] : 0;
55
- $unit = ! empty( $value['unit'] ) ? $value['unit'] : 'days';
56
-
57
- ?><div class="sowb-relative-date" data-name="<?php echo esc_attr( $name ) ?>"><span><?php
58
- echo esc_html( $label );
59
- ?></span><input type="number" min="0" step="1" class="sowb-relative-date-value" value="<?php echo esc_attr( $val ) ?>"/>
60
- <select class="sowb-relative-date-unit">
61
- <?php foreach( $units as $value => $label) : ?>
62
- <option value="<?php echo esc_attr( $value ) ?>" <?php selected( $value, $unit ) ?>><?php echo $label ?></option>
63
- <?php endforeach; ?>
64
- </select><span><?php _e( 'ago', 'so-widgets-bundle' ); ?></span></div><?php
65
- }
66
-
67
- private function get_units() {
68
- return array(
69
- 'days' => __( 'days', 'so-widgets-bundle' ),
70
- 'weeks' => __( 'weeks', 'so-widgets-bundle' ),
71
- 'months' => __( 'months', 'so-widgets-bundle' ),
72
- 'years' => __( 'years', 'so-widgets-bundle' ),
73
- );
74
- }
75
-
76
- public function enqueue_scripts() {
77
- wp_register_style( 'sowb-pikaday', plugin_dir_url(__FILE__) . 'js/lib/pikaday/pikaday.css' );
78
- wp_register_script( 'sowb-pikaday', plugin_dir_url(__FILE__) . 'js/lib/pikaday/pikaday' . SOW_BUNDLE_JS_SUFFIX . '.js', array( ), '1.5.1' );
79
- wp_enqueue_style( 'so-date-range-field', plugin_dir_url(__FILE__) . 'css/date-range-field.css', array( 'sowb-pikaday' ), SOW_BUNDLE_VERSION );
80
- wp_enqueue_script( 'so-date-range-field', plugin_dir_url(__FILE__) . 'js/date-range-field' . SOW_BUNDLE_JS_SUFFIX . '.js', array( 'jquery', 'sowb-pikaday' ), SOW_BUNDLE_VERSION );
81
- }
82
-
83
- protected function sanitize_field_input( $value, $instance ) {
84
- if ( $this->date_type == 'specific' ) {
85
- if ( ! empty( $value ) ) {
86
- $value = json_decode(
87
- $value,
88
- true
89
- );
90
- if ( ! empty( $value['after'] ) ) {
91
- $value_after = new DateTime( $value['after'] );
92
- $value['after'] = $value_after->format( 'Y-m-d' );
93
- }
94
- if ( ! empty( $value['before'] ) ) {
95
- $value_before = new DateTime( $value['before'] );
96
- $value['before'] = $value_before->format( 'Y-m-d' );
97
- }
98
- } else {
99
- $value = array( 'after' => '', 'before' => '' );
100
- }
101
- } else if ( $this->date_type == 'relative' ) {
102
- if ( ! empty( $value ) ) {
103
- $value = json_decode(
104
- $value,
105
- true
106
- );
107
- $unit_keys = array_keys( $this->get_units() );
108
- foreach( array( 'from', 'to' ) as $key ) {
109
- if ( empty( $value[$key] ) ) {
110
- $value[$key] = array();
111
- }
112
- $item = $value[$key];
113
- $val = empty( $item['value'] ) ? 0 : intval( $item['value'] );
114
- $unit = ( ! empty( $item['unit'] ) && in_array( $item['unit'], $unit_keys ) ) ? $item['unit'] : $unit_keys[0];
115
- $value[$key] = array( 'value' => $val, 'unit' => $unit );
116
- }
117
- } else {
118
- $value = array( 'from' => array(), 'to' => array() );
119
- }
120
- }
121
- return json_encode( $value );
122
- }
123
- }
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Widget_Field_Date_Range
5
+ */
6
+ class SiteOrigin_Widget_Field_Date_Range extends SiteOrigin_Widget_Field_Base {
7
+
8
+ /**
9
+ * Either 'relative' or 'specific'. Whether to allow relative or specific date selection.
10
+ *
11
+ * @access protected
12
+ * @var array
13
+ */
14
+ protected $date_type;
15
+
16
+ protected function render_field( $value, $instance ) {
17
+
18
+ if ( $this->date_type == 'specific' ) {
19
+ $this->render_specific_date_selector();
20
+ } else {
21
+ $this->render_relative_date_selector( $value );
22
+ }
23
+ ?><input type="hidden"
24
+ class="siteorigin-widget-input"
25
+ value="<?php echo esc_attr( $value ) ?>"
26
+ name="<?php echo esc_attr( $this->element_name ) ?>" /><?php
27
+ }
28
+
29
+ private function render_specific_date_selector() {
30
+ ?><div class="sowb-specific-date-after"><span><?php
31
+ _ex( 'From', 'From this date', 'so-widgets-bundle' );
32
+ ?></span><input type="text" class="datepicker after-picker"/></div><?php
33
+ ?><div class="sowb-specific-date-before"><span><?php
34
+ _e( 'to', 'so-widgets-bundle' );
35
+ ?></span><input type="text" class="datepicker before-picker"/></div><?php
36
+ }
37
+
38
+ private function render_relative_date_selector( $value ) {
39
+ $value = json_decode(
40
+ $value,
41
+ true
42
+ );
43
+
44
+ $from = ! empty( $value['from'] ) ? $value['from'] : array();
45
+ $this->render_relative_date_selector_part( 'from', __( 'From', 'so-widgets-bundle' ), $from );
46
+
47
+ $to = ! empty( $value['to'] ) ? $value['to'] : array();
48
+ $this->render_relative_date_selector_part( 'to', __( 'to', 'so-widgets-bundle' ), $to );
49
+ }
50
+
51
+ private function render_relative_date_selector_part( $name, $label, $value ) {
52
+ $units = $this->get_units();
53
+
54
+ $val = ! empty( $value['value'] ) ? $value['value'] : 0;
55
+ $unit = ! empty( $value['unit'] ) ? $value['unit'] : 'days';
56
+
57
+ ?><div class="sowb-relative-date" data-name="<?php echo esc_attr( $name ) ?>"><span><?php
58
+ echo esc_html( $label );
59
+ ?></span><input type="number" min="0" step="1" class="sowb-relative-date-value" value="<?php echo esc_attr( $val ) ?>"/>
60
+ <select class="sowb-relative-date-unit">
61
+ <?php foreach( $units as $value => $label) : ?>
62
+ <option value="<?php echo esc_attr( $value ) ?>" <?php selected( $value, $unit ) ?>><?php echo $label ?></option>
63
+ <?php endforeach; ?>
64
+ </select><span><?php _e( 'ago', 'so-widgets-bundle' ); ?></span></div><?php
65
+ }
66
+
67
+ private function get_units() {
68
+ return array(
69
+ 'days' => __( 'days', 'so-widgets-bundle' ),
70
+ 'weeks' => __( 'weeks', 'so-widgets-bundle' ),
71
+ 'months' => __( 'months', 'so-widgets-bundle' ),
72
+ 'years' => __( 'years', 'so-widgets-bundle' ),
73
+ );
74
+ }
75
+
76
+ public function enqueue_scripts() {
77
+ wp_enqueue_style(
78
+ 'so-date-range-field',
79
+ plugin_dir_url(__FILE__) . 'css/date-range-field.css',
80
+ array( 'sowb-pikaday' ),
81
+ SOW_BUNDLE_VERSION
82
+ );
83
+ wp_enqueue_script(
84
+ 'so-date-range-field',
85
+ plugin_dir_url(__FILE__) . 'js/date-range-field' . SOW_BUNDLE_JS_SUFFIX . '.js',
86
+ array( 'jquery', 'sowb-pikaday' ),
87
+ SOW_BUNDLE_VERSION
88
+ );
89
+ }
90
+
91
+ protected function sanitize_field_input( $value, $instance ) {
92
+ if ( $this->date_type == 'specific' ) {
93
+ if ( ! empty( $value ) ) {
94
+ $value = json_decode(
95
+ $value,
96
+ true
97
+ );
98
+ if ( ! empty( $value['after'] ) ) {
99
+ $value_after = new DateTime( $value['after'] );
100
+ $value['after'] = $value_after->format( 'Y-m-d' );
101
+ }
102
+ if ( ! empty( $value['before'] ) ) {
103
+ $value_before = new DateTime( $value['before'] );
104
+ $value['before'] = $value_before->format( 'Y-m-d' );
105
+ }
106
+ } else {
107
+ $value = array( 'after' => '', 'before' => '' );
108
+ }
109
+ } else if ( $this->date_type == 'relative' ) {
110
+ if ( ! empty( $value ) ) {
111
+ $value = json_decode(
112
+ $value,
113
+ true
114
+ );
115
+ $unit_keys = array_keys( $this->get_units() );
116
+ foreach( array( 'from', 'to' ) as $key ) {
117
+ if ( empty( $value[$key] ) ) {
118
+ $value[$key] = array();
119
+ }
120
+ $item = $value[$key];
121
+ $val = empty( $item['value'] ) ? 0 : intval( $item['value'] );
122
+ $unit = ( ! empty( $item['unit'] ) && in_array( $item['unit'], $unit_keys ) ) ? $item['unit'] : $unit_keys[0];
123
+ $value[$key] = array( 'value' => $val, 'unit' => $unit );
124
+ }
125
+ } else {
126
+ $value = array( 'from' => array(), 'to' => array() );
127
+ }
128
+ }
129
+ return json_encode( $value );
130
+ }
131
+ }
base/inc/fields/js/date-range-field.js CHANGED
@@ -1,83 +1,100 @@
1
- /* global jQuery, soWidgets */
2
-
3
- (function( $ ) {
4
- $( document ).on( 'sowsetupformfield', '.siteorigin-widget-field-type-date-range', function ( e ) {
5
-
6
- var valField = $( this ).find( 'input[type="hidden"][class="siteorigin-widget-input"]' );
7
-
8
- if ( $( this ).find( '[class*="sowb-specific-date"]' ).length > 0 ) {
9
- var createPikadayInput = function ( inputName, initVal ) {
10
- var $field = $( this ).find( '.' + inputName + '-picker' );
11
- var picker = new Pikaday( {
12
- field: $field[ 0 ],
13
- blurFieldOnSelect: false,
14
- onSelect: function ( date ) {
15
- var curVal = valField.val() === '' ? {} : JSON.parse( valField.val() );
16
- curVal[ inputName ] = date.toLocaleDateString( {}, {
17
- year: 'numeric',
18
- month: '2-digit',
19
- day: '2-digit'
20
- } );
21
- $field.val( curVal[ inputName ] );
22
- valField.val( JSON.stringify( curVal ) );
23
- valField.trigger( 'change', { silent: true } );
24
- },
25
- } );
26
-
27
- // We trigger the change event on the hidden value field, so prevent 'change' from individual date inputs.
28
- $field.change( function ( event ) {
29
- event.preventDefault();
30
- return false;
31
- } );
32
-
33
- if ( initVal ) {
34
- $field.val( initVal );
35
- }
36
- return picker;
37
- }.bind( this );
38
-
39
- var initRange = valField.val() === '' ? { after: '', before: '' } : JSON.parse( valField.val() );
40
- var afterPicker = createPikadayInput( 'after', initRange.after );
41
- var beforePicker = createPikadayInput( 'before', initRange.before );
42
-
43
- valField.change( function ( event, data ) {
44
- if ( ! ( data && data.silent ) ) {
45
- var newRange = valField.val() === '' ? { after: '', before: '' } : JSON.parse( valField.val() );
46
- afterPicker.setDate( newRange.after );
47
- beforePicker.setDate( newRange.before );
48
- }
49
- } );
50
- } else if ( $( this ).find( '.sowb-relative-date' ).length > 0 ) {
51
-
52
- $( this ).find( '.sowb-relative-date' ).each( function () {
53
- var $name = $( this ).data( 'name' );
54
-
55
- $( this ).change( function () {
56
- var range = valField.val() === '' ? {} : JSON.parse( valField.val() );
57
-
58
- if ( ! range.hasOwnProperty( $name ) ) {
59
- range[ $name ] = {};
60
- }
61
-
62
- range[ $name ][ 'value' ] = $( this ).find( '> input' ).val();
63
- range[ $name ][ 'unit' ] = $( this ).find( '> select' ).val();
64
-
65
- valField.val( JSON.stringify( range ) );
66
- valField.trigger( 'change', { silent: true } );
67
- }.bind( this ) );
68
-
69
- valField.change( function ( event, data ) {
70
- if ( ! ( data && data.silent ) ) {
71
- var range = valField.val() === '' ? { from: {}, to: {} } : JSON.parse( valField.val() );
72
-
73
- if ( range.hasOwnProperty( $name ) ) {
74
- $( this ).find( '> input' ).val( range[ $name ][ 'value' ] );
75
- $( this ).find( '> select' ).val( range[ $name ][ 'unit' ] );
76
- }
77
- }
78
- }.bind( this ) );
79
-
80
- } );
81
- }
82
- } );
83
- })( jQuery );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global jQuery, pikaday */
2
+
3
+ (function( $ ) {
4
+ $( document ).on( 'sowsetupformfield', '.siteorigin-widget-field-type-date-range', function ( e ) {
5
+ var $dateRangeField = $( this );
6
+ var valField = $dateRangeField.find( 'input[type="hidden"][class="siteorigin-widget-input"]' );
7
+
8
+ if ( $dateRangeField.data( 'initialized' ) ) {
9
+ return;
10
+ }
11
+
12
+ if ( $dateRangeField.find( '[class*="sowb-specific-date"]' ).length > 0 ) {
13
+ var createPikadayInput = function ( inputName, initVal ) {
14
+ var $field = $dateRangeField.find( '.' + inputName + '-picker' );
15
+ var picker = new Pikaday( {
16
+ field: $field[ 0 ],
17
+ blurFieldOnSelect: false,
18
+ toString: function( date, format ) {
19
+ var day = date.getDate();
20
+ day = day < 10 ? '0' + day.toString() : day.toString();
21
+ var month = date.getMonth() + 1;
22
+ month = month < 10 ? '0' + month.toString() : month.toString();
23
+ var year = date.getFullYear();
24
+ return year + '-' + month + '-' + day;
25
+ },
26
+ parse: function( dateString, format ) {
27
+
28
+ var parts = dateString.split( '-' );
29
+ var day = parseInt( parts[2] );
30
+ var month = parseInt( parts[1] ) - 1;
31
+ var year = parseInt( parts[0] );
32
+ return new Date(year, month, day);
33
+ },
34
+ onSelect: function ( date ) {
35
+ var curVal = valField.val() === '' ? {} : JSON.parse( valField.val() );
36
+ curVal[ inputName ] = this.toString( date, this.format );
37
+ $field.val( curVal[ inputName ] );
38
+ valField.val( JSON.stringify( curVal ) );
39
+ valField.trigger( 'change', { silent: true } );
40
+ },
41
+ } );
42
+
43
+ // We trigger the change event on the hidden value field, so prevent 'change' from individual date inputs.
44
+ $field.change( function ( event ) {
45
+ event.preventDefault();
46
+ return false;
47
+ } );
48
+
49
+ if ( initVal ) {
50
+ $field.val( initVal );
51
+ }
52
+ return picker;
53
+ }.bind( this );
54
+
55
+ var initRange = valField.val() === '' ? { after: '', before: '' } : JSON.parse( valField.val() );
56
+ var afterPicker = createPikadayInput( 'after', initRange.after );
57
+ var beforePicker = createPikadayInput( 'before', initRange.before );
58
+
59
+ valField.change( function ( event, data ) {
60
+ if ( ! ( data && data.silent ) ) {
61
+ var newRange = valField.val() === '' ? { after: '', before: '' } : JSON.parse( valField.val() );
62
+ afterPicker.setDate( newRange.after );
63
+ beforePicker.setDate( newRange.before );
64
+ }
65
+ } );
66
+ } else if ( $dateRangeField.find( '.sowb-relative-date' ).length > 0 ) {
67
+
68
+ $dateRangeField.find( '.sowb-relative-date' ).each( function () {
69
+ var $name = $( this ).data( 'name' );
70
+
71
+ $( this ).change( function () {
72
+ var range = valField.val() === '' ? {} : JSON.parse( valField.val() );
73
+
74
+ if ( ! range.hasOwnProperty( $name ) ) {
75
+ range[ $name ] = {};
76
+ }
77
+
78
+ range[ $name ][ 'value' ] = $( this ).find( '> input' ).val();
79
+ range[ $name ][ 'unit' ] = $( this ).find( '> select' ).val();
80
+
81
+ valField.val( JSON.stringify( range ) );
82
+ valField.trigger( 'change', { silent: true } );
83
+ }.bind( this ) );
84
+
85
+ valField.change( function ( event, data ) {
86
+ if ( ! ( data && data.silent ) ) {
87
+ var range = valField.val() === '' ? { from: {}, to: {} } : JSON.parse( valField.val() );
88
+
89
+ if ( range.hasOwnProperty( $name ) ) {
90
+ $( this ).find( '> input' ).val( range[ $name ][ 'value' ] );
91
+ $( this ).find( '> select' ).val( range[ $name ][ 'unit' ] );
92
+ }
93
+ }
94
+ }.bind( this ) );
95
+
96
+ } );
97
+ }
98
+ $dateRangeField.data( 'initialized', true );
99
+ } );
100
+ })( jQuery );
base/inc/fields/js/date-range-field.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){e(document).on("sowsetupformfield",".siteorigin-widget-field-type-date-range",function(t){var i=e(this).find('input[type="hidden"][class="siteorigin-widget-input"]');if(e(this).find('[class*="sowb-specific-date"]').length>0){var a=function(t,a){var n=e(this).find("."+t+"-picker"),r=new Pikaday({field:n[0],blurFieldOnSelect:!1,onSelect:function(e){var a=""===i.val()?{}:JSON.parse(i.val());a[t]=e.toLocaleDateString({},{year:"numeric",month:"2-digit",day:"2-digit"}),n.val(a[t]),i.val(JSON.stringify(a)),i.trigger("change",{silent:!0})}});return n.change(function(e){return e.preventDefault(),!1}),a&&n.val(a),r}.bind(this),n=""===i.val()?{after:"",before:""}:JSON.parse(i.val()),r=a("after",n.after),s=a("before",n.before);i.change(function(e,t){if(!t||!t.silent){var a=""===i.val()?{after:"",before:""}:JSON.parse(i.val());r.setDate(a.after),s.setDate(a.before)}})}else e(this).find(".sowb-relative-date").length>0&&e(this).find(".sowb-relative-date").each(function(){var t=e(this).data("name");e(this).change(function(){var a=""===i.val()?{}:JSON.parse(i.val());a.hasOwnProperty(t)||(a[t]={}),a[t].value=e(this).find("> input").val(),a[t].unit=e(this).find("> select").val(),i.val(JSON.stringify(a)),i.trigger("change",{silent:!0})}.bind(this)),i.change(function(a,n){if(!n||!n.silent){var r=""===i.val()?{from:{},to:{}}:JSON.parse(i.val());r.hasOwnProperty(t)&&(e(this).find("> input").val(r[t].value),e(this).find("> select").val(r[t].unit))}}.bind(this))})})}(jQuery);
1
+ !function(t){t(document).on("sowsetupformfield",".siteorigin-widget-field-type-date-range",function(e){var i=t(this),n=i.find('input[type="hidden"][class="siteorigin-widget-input"]');if(!i.data("initialized")){if(i.find('[class*="sowb-specific-date"]').length>0){var a=function(t,e){var a=i.find("."+t+"-picker"),r=new Pikaday({field:a[0],blurFieldOnSelect:!1,toString:function(t,e){var i=t.getDate();i=i<10?"0"+i.toString():i.toString();var n=t.getMonth()+1;return n=n<10?"0"+n.toString():n.toString(),t.getFullYear()+"-"+n+"-"+i},parse:function(t,e){var i=t.split("-"),n=parseInt(i[2]),a=parseInt(i[1])-1,r=parseInt(i[0]);return new Date(r,a,n)},onSelect:function(e){var i=""===n.val()?{}:JSON.parse(n.val());i[t]=this.toString(e,this.format),a.val(i[t]),n.val(JSON.stringify(i)),n.trigger("change",{silent:!0})}});return a.change(function(t){return t.preventDefault(),!1}),e&&a.val(e),r}.bind(this),r=""===n.val()?{after:"",before:""}:JSON.parse(n.val()),s=a("after",r.after),l=a("before",r.before);n.change(function(t,e){if(!e||!e.silent){var i=""===n.val()?{after:"",before:""}:JSON.parse(n.val());s.setDate(i.after),l.setDate(i.before)}})}else i.find(".sowb-relative-date").length>0&&i.find(".sowb-relative-date").each(function(){var e=t(this).data("name");t(this).change(function(){var i=""===n.val()?{}:JSON.parse(n.val());i.hasOwnProperty(e)||(i[e]={}),i[e].value=t(this).find("> input").val(),i[e].unit=t(this).find("> select").val(),n.val(JSON.stringify(i)),n.trigger("change",{silent:!0})}.bind(this)),n.change(function(i,a){if(!a||!a.silent){var r=""===n.val()?{from:{},to:{}}:JSON.parse(n.val());r.hasOwnProperty(e)&&(t(this).find("> input").val(r[e].value),t(this).find("> select").val(r[e].unit))}}.bind(this))});i.data("initialized",!0)}})}(jQuery);
base/inc/fields/js/media-field.js CHANGED
@@ -1,408 +1,409 @@
1
- /* global jQuery, soWidgets */
2
-
3
- ( function( $ ) {
4
-
5
- $(document).on( 'sowsetupformfield', '.siteorigin-widget-field-type-media', function(e) {
6
- var $field = $( this );
7
- var $media = $field.find('> .media-field-wrapper');
8
- var $inputField = $field.find( '.siteorigin-widget-input' ).not('.media-fallback-external');
9
-
10
- if ( $media.data( 'initialized' ) ) {
11
- return;
12
- }
13
-
14
- // Handle the media uploader
15
- $media.find( '.media-upload-button' ).click(function(e){
16
- e.preventDefault();
17
- if( typeof wp.media === 'undefined' ) {
18
- return;
19
- }
20
-
21
- var $$ = $(this);
22
- var frame = $(this ).data('frame');
23
-
24
- // If the media frame already exists, reopen it.
25
- if ( frame ) {
26
- frame.open();
27
- return false;
28
- }
29
-
30
- // Create the media frame.
31
- frame = wp.media( {
32
- // Set the title of the modal.
33
- title: $$.data('choose'),
34
-
35
- // Tell the modal to show only images.
36
- library: {
37
- type: $$.data('library').split(',').map(function(v){ return v.trim(); })
38
- },
39
-
40
- // Customize the submit button.
41
- button: {
42
- // Set the text of the button.
43
- text: $$.data('update'),
44
- // Tell the button not to close the modal, since we're
45
- // going to refresh the page when the image is selected.
46
- close: false
47
- }
48
- } );
49
-
50
- // Store the frame
51
- $$.data('frame', frame);
52
-
53
- // When an image is selected, run a callback.
54
- frame.on( 'select', function() {
55
- // Grab the selected attachment.
56
- var attachment = frame.state().get('selection').first().attributes;
57
-
58
- $field.find('.current .title' ).html(attachment.title);
59
- $inputField.val(attachment.id);
60
- $inputField.trigger( 'change', { silent: true } );
61
-
62
- var $thumbnail = $field.find( '.current .thumbnail' );
63
-
64
- if(typeof attachment.sizes !== 'undefined'){
65
- if(typeof attachment.sizes.thumbnail !== 'undefined'){
66
- $thumbnail.attr('src', attachment.sizes.thumbnail.url).fadeIn();
67
- }
68
- else {
69
- $thumbnail.attr('src', attachment.sizes.full.url).fadeIn();
70
- }
71
- }
72
- else{
73
- $thumbnail.attr('src', attachment.icon).fadeIn();
74
- }
75
-
76
- $field.find('.media-remove-button').removeClass('remove-hide');
77
-
78
- frame.close();
79
- } );
80
-
81
- // Finally, open the modal.
82
- frame.open();
83
- });
84
-
85
- $media.find('.current' )
86
- .mouseenter(function(){
87
- var t = $(this ).find('.title' );
88
- if( t.html() !== ''){
89
- t.fadeIn('fast');
90
- }
91
- })
92
- .mouseleave(function(){
93
- $(this ).find('.title' ).clearQueue().fadeOut('fast');
94
- });
95
-
96
- $field.find('a.media-remove-button' )
97
- .click( function( e ){
98
- e.preventDefault();
99
- $field.find('.current .title' ).html('');
100
- $inputField.val('');
101
- $field.find('.current .thumbnail' ).fadeOut('fast');
102
- $(this).addClass('remove-hide');
103
- } );
104
-
105
- // Everything for the dialog
106
- var dialog;
107
-
108
- var reflowDialog = function() {
109
- if( ! dialog ) return;
110
-
111
- var results = dialog.find('.so-widgets-image-results');
112
- if( results.length === 0 ) return;
113
-
114
- var width = results.width(),
115
- perRow = Math.floor( width / 276 ),
116
- spare = ( width - perRow * 276 ),
117
- resultWidth = spare / perRow + 260;
118
-
119
- results.find( '.so-widgets-result-image' ).css( {
120
- 'width' : resultWidth,
121
- 'height' : resultWidth / 1.4
122
- } );
123
- };
124
- $(window).resize( reflowDialog );
125
-
126
- var setupDialog = function(){
127
- if( ! dialog ) {
128
- // Create the dialog
129
- dialog = $( $('#so-widgets-bundle-tpl-image-search-dialog').html().trim() ).appendTo( 'body' );
130
- dialog.find( '.close' ).click( function(){
131
- dialog.hide();
132
- } );
133
-
134
- var results = dialog.find( '.so-widgets-image-results' );
135
-
136
- var fetchImages = function( query, page ){
137
- dialog.find( '.so-widgets-results-loading' ).fadeIn('fast');
138
- dialog.find( '.so-widgets-results-loading strong' ).html(
139
- dialog.find( '.so-widgets-results-loading strong' ).data( 'loading' )
140
- );
141
- dialog.find( '.so-widgets-results-more' ).hide();
142
-
143
- $.get(
144
- ajaxurl,
145
- {
146
- 'action' : 'so_widgets_image_search',
147
- 'q' : query,
148
- 'page' : page,
149
- '_sononce' : dialog.find('input[name="_sononce"]').val()
150
- },
151
- function( response ){
152
- if( response.error ) {
153
- alert( response.message );
154
- return;
155
- }
156
-
157
- results.removeClass( 'so-loading' );
158
- $.each( response.items, function( i, r ){
159
- var result = $( $('#so-widgets-bundle-tpl-image-search-result').html().trim() )
160
- .appendTo( results )
161
- .addClass( 'source-' + r.source );
162
- var img = result.find('.so-widgets-result-image');
163
-
164
- // Preload the image
165
- img.css( 'background-image', 'url(' + r.thumbnail + ')' );
166
- img.data( 'thumbnail', r.thumbnail );
167
- img.data( 'preview', r.preview );
168
-
169
- if( r.url ) {
170
- img.attr( {
171
- 'href': r.url,
172
- 'target': '_blank'
173
- } );
174
- }
175
-
176
- if( r.full_url ) {
177
- img.data( {
178
- 'full_url' : r.full_url,
179
- 'import_signature' : r.import_signature
180
- } );
181
- img.attr( 'href', r.full_url );
182
- }
183
-
184
- if( r.source === 'shutterstock' ) {
185
- img.append( $('#so-widgets-bundle-tpl-image-search-result-sponsored').html() );
186
- }
187
- } );
188
-
189
- if( page === 1 ) {
190
- dialog.find('#so-widgets-image-search-suggestions ul').empty();
191
- $.each( response.keywords, function( i, r ){
192
- dialog.find('#so-widgets-image-search-suggestions').show();
193
- dialog.find('#so-widgets-image-search-suggestions ul').append(
194
- $('<li></li>') . append( $('<a href="#"></a>').html( r ).data( 'keyword', r ) )
195
- );
196
- } );
197
- }
198
-
199
- dialog.find( '.so-widgets-results-loading' ).fadeOut('fast');
200
-
201
- reflowDialog();
202
- dialog
203
- .find( '.so-widgets-results-more' ).show()
204
- .find( 'button' ).data( { 'query': query, 'page' : page+1 } );
205
- }
206
- );
207
-
208
- };
209
-
210
- // Setup the search
211
- dialog.find('#so-widgets-image-search-form').submit( function( e ){
212
- e.preventDefault();
213
-
214
- // Perform the search
215
- var q = dialog.find('.so-widgets-search-input').val();
216
- results.empty();
217
-
218
- if( q !== '' ) {
219
- // Send the query to the server
220
- fetchImages( q, 1 );
221
- }
222
- } );
223
-
224
- // Clicking on the related search buttons
225
- dialog.on( 'click', '.so-keywords-list a', function( e ){
226
- e.preventDefault();
227
- var $$ = $(this).blur();
228
- dialog.find('.so-widgets-search-input').val( $$.data( 'keyword' ) );
229
- dialog.find('#so-widgets-image-search-form').submit();
230
- } );
231
-
232
- // Clicking on the more button
233
- dialog.find('.so-widgets-results-more button').click( function(){
234
- var $$ = $(this);
235
- fetchImages( $$.data( 'query' ), $$.data( 'page' ) );
236
- } );
237
-
238
- var hoverTimeout;
239
-
240
- // Clicking on an image to import it
241
- dialog.on( 'click', '.so-widgets-result-image', function( e ){
242
- var $$ = $(this);
243
- if( ! $$.data( 'full_url' ) ) {
244
- return;
245
- }
246
-
247
- e.preventDefault();
248
-
249
- if( confirm( dialog.data('confirm-import') ) ) {
250
- dialog.addClass( 'so-widgets-importing' );
251
-
252
- var postId = $( '#post_ID' ).val();
253
- if( postId === null ) {
254
- postId = '';
255
- }
256
-
257
- // Send the message to import the URL
258
- $.get(
259
- ajaxurl,
260
- {
261
- 'action' : 'so_widgets_image_import',
262
- 'full_url' : $$.data( 'full_url' ),
263
- 'import_signature' : $$.data( 'import_signature' ),
264
- 'post_id' : postId,
265
- '_sononce' : dialog.find('input[name="_sononce"]').val()
266
- },
267
- function( response ) {
268
- dialog.find('#so-widgets-image-search-frame').removeClass( 'so-widgets-importing' );
269
-
270
- if( response.error === false ) {
271
- // This was a success
272
- dialog.hide();
273
- dialog.find( '.so-widgets-results-loading' ).hide();
274
- $inputField.val( response.attachment_id ).trigger('change', { silent: true } );
275
- $field.find('.current .thumbnail' ).attr('src', response.thumb ).fadeIn();
276
-
277
- $field.find('.media-remove-button').removeClass('remove-hide');
278
- }
279
- else {
280
- alert( response.message );
281
- dialog.find( '.so-widgets-results-loading' ).hide();
282
- }
283
- }
284
- );
285
-
286
- // Clear the dialog
287
- dialog.find( '.so-widgets-results-loading' ).fadeIn('fast');
288
- dialog.find( '.so-widgets-results-loading strong' ).html(
289
- dialog.find( '.so-widgets-results-loading strong' ).data( 'importing' )
290
- );
291
- dialog.find( '.so-widgets-results-more' ).hide();
292
- dialog.find('#so-widgets-image-search-frame').addClass( 'so-widgets-importing' );
293
- }
294
- } );
295
-
296
- // Hovering over an image to preview it
297
- var previewWindow = dialog.find('.so-widgets-preview-window');
298
- dialog
299
- .on( 'mouseenter', '.so-widgets-result-image', function(){
300
- var $$ = $(this),
301
- preview = $$.data('preview');
302
-
303
- clearTimeout( hoverTimeout );
304
-
305
- hoverTimeout = setTimeout( function(){
306
- // Scale the preview sizes
307
- var scalePreviewX = 1, scalePreviewY = 1;
308
- if( preview[1] > $( window ).outerWidth() *0.33 ) {
309
- scalePreviewX = $( window ).outerWidth() *0.33 / preview[1];
310
- }
311
- if( preview[2] > $( window ).outerHeight() *0.5 ) {
312
- scalePreviewY = $( window ).outerHeight() *0.5 / preview[2];
313
- }
314
- var scalePreview = Math.min( scalePreviewX, scalePreviewY );
315
- // Never upscale
316
- if( scalePreview > 1 ) {
317
- scalePreview = 1;
318
- }
319
-
320
- previewWindow.show()
321
- .find('.so-widgets-preview-window-inside')
322
- .css( {
323
- 'background-image' : 'url(' + $$.data('thumbnail') + ')',
324
- 'width' : preview[1] * scalePreview,
325
- 'height' : preview[2] * scalePreview
326
- } )
327
- .append( $( '<img />' ).attr( 'src', preview[0] ) );
328
-
329
- dialog.trigger('mousemove');
330
- }, 1000 );
331
-
332
- } )
333
- .on( 'mouseleave', '.so-widgets-result-image', function(){
334
- previewWindow.hide().find('img').remove();
335
- clearTimeout( hoverTimeout );
336
- } );
337
-
338
- var lastX, lastY;
339
- dialog.on( 'mousemove', function( e ){
340
- if( e.clientX ) lastX = e.clientX;
341
- if( e.clientY ) lastY = e.clientY;
342
-
343
- if( previewWindow.is( ':visible' ) ) {
344
- var ph = previewWindow.outerHeight(),
345
- pw = previewWindow.outerWidth(),
346
- wh = $( window ).outerHeight(),
347
- ww = $( window ).outerWidth();
348
-
349
-
350
- // Calculate the top position
351
- var top = lastY - ph/2;
352
- top = Math.max( top, 10 );
353
- top = Math.min( top, wh - 10 - ph );
354
-
355
- // Calculate the left position
356
- var left = (lastX < ww/2) ? lastX + 15 : lastX - 15 - pw;
357
-
358
- // Figure out where the preview needs to go
359
- previewWindow.css({
360
- 'top': top,
361
- 'left': left
362
- });
363
-
364
- }
365
- } );
366
- }
367
-
368
- dialog.show();
369
- dialog.find( '.so-widgets-search-input' ).focus();
370
- };
371
-
372
- // Handle displaying the image search dialog
373
- $media.find( '.find-image-button' ).click( function(e){
374
- e.preventDefault();
375
- setupDialog();
376
- } );
377
-
378
- $inputField.change( function ( event, data ) {
379
- if ( ! ( data && data.silent ) ) {
380
- var newVal = $inputField.val();
381
- if ( newVal) {
382
- var $thumbnail = $field.find( '.current .thumbnail' );
383
- var attachment = wp.media.attachment( newVal );
384
- attachment.fetch().done( function () {
385
- if ( attachment.has( 'sizes' ) ) {
386
- var sizes = attachment.get( 'sizes' );
387
- if ( typeof sizes.thumbnail !== 'undefined' ) {
388
- $thumbnail.attr( 'src', sizes.thumbnail.url ).fadeIn();
389
- }
390
- else {
391
- $thumbnail.attr( 'src', sizes.full.url ).fadeIn();
392
- }
393
- }
394
- else {
395
- $thumbnail.attr( 'src', attachment.get('icon') ).fadeIn();
396
- }
397
- $field.find('.media-remove-button').removeClass('remove-hide');
398
- } );
399
- } else {
400
- $field.find( 'a.media-remove-button' ).click();
401
- }
402
- }
403
- } );
404
-
405
- $media.data( 'initialized', true );
406
- });
407
-
408
- } )( jQuery );
 
1
+ /* global jQuery, soWidgets */
2
+
3
+ ( function( $ ) {
4
+
5
+ $(document).on( 'sowsetupformfield', '.siteorigin-widget-field-type-media', function(e) {
6
+ var $field = $( this );
7
+ var $media = $field.find('> .media-field-wrapper');
8
+ var $inputField = $field.find( '.siteorigin-widget-input' ).not('.media-fallback-external');
9
+
10
+ if ( $media.data( 'initialized' ) ) {
11
+ return;
12
+ }
13
+
14
+ // Handle the media uploader
15
+ $media.find( '.media-upload-button' ).click(function(e){
16
+ e.preventDefault();
17
+ if( typeof wp.media === 'undefined' ) {
18
+ return;
19
+ }
20
+
21
+ var $$ = $(this);
22
+ var frame = $(this ).data('frame');
23
+
24
+ // If the media frame already exists, reopen it.
25
+ if ( frame ) {
26
+ frame.open();
27
+ return false;
28
+ }
29
+
30
+ // Create the media frame.
31
+ frame = wp.media( {
32
+ // Set the title of the modal.
33
+ title: $$.data('choose'),
34
+
35
+ // Tell the modal to show only images.
36
+ library: {
37
+ type: $$.data('library').split(',').map(function(v){ return v.trim(); })
38
+ },
39
+
40
+ // Customize the submit button.
41
+ button: {
42
+ // Set the text of the button.
43
+ text: $$.data('update'),
44
+ // Tell the button not to close the modal, since we're
45
+ // going to refresh the page when the image is selected.
46
+ close: false
47
+ }
48
+ } );
49
+
50
+ // Store the frame
51
+ $$.data('frame', frame);
52
+
53
+ // When an image is selected, run a callback.
54
+ frame.on( 'select', function() {
55
+ // Grab the selected attachment.
56
+ var attachment = frame.state().get('selection').first().attributes;
57
+
58
+ $field.find('.current .title' ).html(attachment.title);
59
+ $inputField.val(attachment.id);
60
+ $inputField.trigger( 'change', { silent: true } );
61
+
62
+ var $thumbnail = $field.find( '.current .thumbnail' );
63
+
64
+ if(typeof attachment.sizes !== 'undefined'){
65
+ if(typeof attachment.sizes.thumbnail !== 'undefined'){
66
+ $thumbnail.attr('src', attachment.sizes.thumbnail.url).fadeIn();
67
+ }
68
+ else {
69
+ $thumbnail.attr('src', attachment.sizes.full.url).fadeIn();
70
+ }
71
+ }
72
+ else{
73
+ $thumbnail.attr('src', attachment.icon).fadeIn();
74
+ }
75
+
76
+ $field.find('.media-remove-button').removeClass('remove-hide');
77
+
78
+ frame.close();
79
+ } );
80
+
81
+ // Finally, open the modal.
82
+ frame.open();
83
+ });
84
+
85
+ $media.find('.current' )
86
+ .mouseenter(function(){
87
+ var t = $(this ).find('.title' );
88
+ if( t.html() !== ''){
89
+ t.fadeIn('fast');
90
+ }
91
+ })
92
+ .mouseleave(function(){
93
+ $(this ).find('.title' ).clearQueue().fadeOut('fast');
94
+ });
95
+
96
+ $field.find('a.media-remove-button' )
97
+ .click( function( e ){
98
+ e.preventDefault();
99
+ $field.find('.current .title' ).html('');
100
+ $inputField.val('');
101
+ $inputField.trigger( 'change', { silent: true } );
102
+ $field.find('.current .thumbnail' ).fadeOut('fast');
103
+ $(this).addClass('remove-hide');
104
+ } );
105
+
106
+ // Everything for the dialog
107
+ var dialog;
108
+
109
+ var reflowDialog = function() {
110
+ if( ! dialog ) return;
111
+
112
+ var results = dialog.find('.so-widgets-image-results');
113
+ if( results.length === 0 ) return;
114
+
115
+ var width = results.width(),
116
+ perRow = Math.floor( width / 276 ),
117
+ spare = ( width - perRow * 276 ),
118
+ resultWidth = spare / perRow + 260;
119
+
120
+ results.find( '.so-widgets-result-image' ).css( {
121
+ 'width' : resultWidth,
122
+ 'height' : resultWidth / 1.4
123
+ } );
124
+ };
125
+ $(window).resize( reflowDialog );
126
+
127
+ var setupDialog = function(){
128
+ if( ! dialog ) {
129
+ // Create the dialog
130
+ dialog = $( $('#so-widgets-bundle-tpl-image-search-dialog').html().trim() ).appendTo( 'body' );
131
+ dialog.find( '.close' ).click( function(){
132
+ dialog.hide();
133
+ } );
134
+
135
+ var results = dialog.find( '.so-widgets-image-results' );
136
+
137
+ var fetchImages = function( query, page ){
138
+ dialog.find( '.so-widgets-results-loading' ).fadeIn('fast');
139
+ dialog.find( '.so-widgets-results-loading strong' ).html(
140
+ dialog.find( '.so-widgets-results-loading strong' ).data( 'loading' )
141
+ );
142
+ dialog.find( '.so-widgets-results-more' ).hide();
143
+
144
+ $.get(
145
+ ajaxurl,
146
+ {
147
+ 'action' : 'so_widgets_image_search',
148
+ 'q' : query,
149
+ 'page' : page,
150
+ '_sononce' : dialog.find('input[name="_sononce"]').val()
151
+ },
152
+ function( response ){
153
+ if( response.error ) {
154
+ alert( response.message );
155
+ return;
156
+ }
157
+
158
+ results.removeClass( 'so-loading' );
159
+ $.each( response.items, function( i, r ){
160
+ var result = $( $('#so-widgets-bundle-tpl-image-search-result').html().trim() )
161
+ .appendTo( results )
162
+ .addClass( 'source-' + r.source );
163
+ var img = result.find('.so-widgets-result-image');
164
+
165
+ // Preload the image
166
+ img.css( 'background-image', 'url(' + r.thumbnail + ')' );
167
+ img.data( 'thumbnail', r.thumbnail );
168
+ img.data( 'preview', r.preview );
169
+
170
+ if( r.url ) {
171
+ img.attr( {
172
+ 'href': r.url,
173
+ 'target': '_blank'
174
+ } );
175
+ }
176
+
177
+ if( r.full_url ) {
178
+ img.data( {
179
+ 'full_url' : r.full_url,
180
+ 'import_signature' : r.import_signature
181
+ } );
182
+ img.attr( 'href', r.full_url );
183
+ }
184
+
185
+ if( r.source === 'shutterstock' ) {
186
+ img.append( $('#so-widgets-bundle-tpl-image-search-result-sponsored').html() );
187
+ }
188
+ } );
189
+
190
+ if( page === 1 ) {
191
+ dialog.find('#so-widgets-image-search-suggestions ul').empty();
192
+ $.each( response.keywords, function( i, r ){
193
+ dialog.find('#so-widgets-image-search-suggestions').show();
194
+ dialog.find('#so-widgets-image-search-suggestions ul').append(
195
+ $('<li></li>') . append( $('<a href="#"></a>').html( r ).data( 'keyword', r ) )
196
+ );
197
+ } );
198
+ }
199
+
200
+ dialog.find( '.so-widgets-results-loading' ).fadeOut('fast');
201
+
202
+ reflowDialog();
203
+ dialog
204
+ .find( '.so-widgets-results-more' ).show()
205
+ .find( 'button' ).data( { 'query': query, 'page' : page+1 } );
206
+ }
207
+ );
208
+
209
+ };
210
+
211
+ // Setup the search
212
+ dialog.find('#so-widgets-image-search-form').submit( function( e ){
213
+ e.preventDefault();
214
+
215
+ // Perform the search
216
+ var q = dialog.find('.so-widgets-search-input').val();
217
+ results.empty();
218
+
219
+ if( q !== '' ) {
220
+ // Send the query to the server
221
+ fetchImages( q, 1 );
222
+ }
223
+ } );
224
+
225
+ // Clicking on the related search buttons
226
+ dialog.on( 'click', '.so-keywords-list a', function( e ){
227
+ e.preventDefault();
228
+ var $$ = $(this).blur();
229
+ dialog.find('.so-widgets-search-input').val( $$.data( 'keyword' ) );
230
+ dialog.find('#so-widgets-image-search-form').submit();
231
+ } );
232
+
233
+ // Clicking on the more button
234
+ dialog.find('.so-widgets-results-more button').click( function(){
235
+ var $$ = $(this);
236
+ fetchImages( $$.data( 'query' ), $$.data( 'page' ) );
237
+ } );
238
+
239
+ var hoverTimeout;
240
+
241
+ // Clicking on an image to import it
242
+ dialog.on( 'click', '.so-widgets-result-image', function( e ){
243
+ var $$ = $(this);
244
+ if( ! $$.data( 'full_url' ) ) {
245
+ return;
246
+ }
247
+
248
+ e.preventDefault();
249
+
250
+ if( confirm( dialog.data('confirm-import') ) ) {
251
+ dialog.addClass( 'so-widgets-importing' );
252
+
253
+ var postId = $( '#post_ID' ).val();
254
+ if( postId === null ) {
255
+ postId = '';
256
+ }
257
+
258
+ // Send the message to import the URL
259
+ $.get(
260
+ ajaxurl,
261
+ {
262
+ 'action' : 'so_widgets_image_import',
263
+ 'full_url' : $$.data( 'full_url' ),
264
+ 'import_signature' : $$.data( 'import_signature' ),
265
+ 'post_id' : postId,
266
+ '_sononce' : dialog.find('input[name="_sononce"]').val()
267
+ },
268
+ function( response ) {
269
+ dialog.find('#so-widgets-image-search-frame').removeClass( 'so-widgets-importing' );
270
+
271
+ if( response.error === false ) {
272
+ // This was a success
273
+ dialog.hide();
274
+ dialog.find( '.so-widgets-results-loading' ).hide();
275
+ $inputField.val( response.attachment_id ).trigger('change', { silent: true } );
276
+ $field.find('.current .thumbnail' ).attr('src', response.thumb ).fadeIn();
277
+
278
+ $field.find('.media-remove-button').removeClass('remove-hide');
279
+ }
280
+ else {
281
+ alert( response.message );
282
+ dialog.find( '.so-widgets-results-loading' ).hide();
283
+ }
284
+ }
285
+ );
286
+
287
+ // Clear the dialog
288
+ dialog.find( '.so-widgets-results-loading' ).fadeIn('fast');
289
+ dialog.find( '.so-widgets-results-loading strong' ).html(
290
+ dialog.find( '.so-widgets-results-loading strong' ).data( 'importing' )
291
+ );
292
+ dialog.find( '.so-widgets-results-more' ).hide();
293
+ dialog.find('#so-widgets-image-search-frame').addClass( 'so-widgets-importing' );
294
+ }
295
+ } );
296
+
297
+ // Hovering over an image to preview it
298
+ var previewWindow = dialog.find('.so-widgets-preview-window');
299
+ dialog
300
+ .on( 'mouseenter', '.so-widgets-result-image', function(){
301
+ var $$ = $(this),
302
+ preview = $$.data('preview');
303
+
304
+ clearTimeout( hoverTimeout );
305
+
306
+ hoverTimeout = setTimeout( function(){
307
+ // Scale the preview sizes
308
+ var scalePreviewX = 1, scalePreviewY = 1;
309
+ if( preview[1] > $( window ).outerWidth() *0.33 ) {
310
+ scalePreviewX = $( window ).outerWidth() *0.33 / preview[1];
311
+ }
312
+ if( preview[2] > $( window ).outerHeight() *0.5 ) {
313
+ scalePreviewY = $( window ).outerHeight() *0.5 / preview[2];
314
+ }
315
+ var scalePreview = Math.min( scalePreviewX, scalePreviewY );
316
+ // Never upscale
317
+ if( scalePreview > 1 ) {
318
+ scalePreview = 1;
319
+ }
320
+
321
+ previewWindow.show()
322
+ .find('.so-widgets-preview-window-inside')
323
+ .css( {
324
+ 'background-image' : 'url(' + $$.data('thumbnail') + ')',
325
+ 'width' : preview[1] * scalePreview,
326
+ 'height' : preview[2] * scalePreview
327
+ } )
328
+ .append( $( '<img />' ).attr( 'src', preview[0] ) );
329
+
330
+ dialog.trigger('mousemove');
331
+ }, 1000 );
332
+
333
+ } )
334
+ .on( 'mouseleave', '.so-widgets-result-image', function(){
335
+ previewWindow.hide().find('img').remove();
336
+ clearTimeout( hoverTimeout );
337
+ } );
338
+
339
+ var lastX, lastY;
340
+ dialog.on( 'mousemove', function( e ){
341
+ if( e.clientX ) lastX = e.clientX;
342
+ if( e.clientY ) lastY = e.clientY;
343
+
344
+ if( previewWindow.is( ':visible' ) ) {
345
+ var ph = previewWindow.outerHeight(),
346
+ pw = previewWindow.outerWidth(),
347
+ wh = $( window ).outerHeight(),
348
+ ww = $( window ).outerWidth();
349
+
350
+
351
+ // Calculate the top position
352
+ var top = lastY - ph/2;
353
+ top = Math.max( top, 10 );
354
+ top = Math.min( top, wh - 10 - ph );
355
+
356
+ // Calculate the left position
357
+ var left = (lastX < ww/2) ? lastX + 15 : lastX - 15 - pw;
358
+
359
+ // Figure out where the preview needs to go
360
+ previewWindow.css({
361
+ 'top': top,
362
+ 'left': left
363
+ });
364
+
365
+ }
366
+ } );
367
+ }
368
+
369
+ dialog.show();
370
+ dialog.find( '.so-widgets-search-input' ).focus();
371
+ };
372
+
373
+ // Handle displaying the image search dialog
374
+ $media.find( '.find-image-button' ).click( function(e){
375
+ e.preventDefault();
376
+ setupDialog();
377
+ } );
378
+
379
+ $inputField.change( function ( event, data ) {
380
+ if ( ! ( data && data.silent ) ) {
381
+ var newVal = $inputField.val();
382
+ if ( newVal) {
383
+ var $thumbnail = $field.find( '.current .thumbnail' );
384
+ var attachment = wp.media.attachment( newVal );
385
+ attachment.fetch().done( function () {
386
+ if ( attachment.has( 'sizes' ) ) {
387
+ var sizes = attachment.get( 'sizes' );
388
+ if ( typeof sizes.thumbnail !== 'undefined' ) {
389
+ $thumbnail.attr( 'src', sizes.thumbnail.url ).fadeIn();
390
+ }
391
+ else {
392
+ $thumbnail.attr( 'src', sizes.full.url ).fadeIn();
393
+ }
394
+ }
395
+ else {
396
+ $thumbnail.attr( 'src', attachment.get('icon') ).fadeIn();
397
+ }
398
+ $field.find('.media-remove-button').removeClass('remove-hide');
399
+ } );
400
+ } else {
401
+ $field.find( 'a.media-remove-button' ).click();
402
+ }
403
+ }
404
+ } );
405
+
406
+ $media.data( 'initialized', true );
407
+ });
408
+
409
+ } )( jQuery );
base/inc/fields/js/media-field.min.js CHANGED
@@ -1 +1 @@
1
- !function(e){e(document).on("sowsetupformfield",".siteorigin-widget-field-type-media",function(t){var i=e(this),a=i.find("> .media-field-wrapper"),s=i.find(".siteorigin-widget-input").not(".media-fallback-external");if(!a.data("initialized")){a.find(".media-upload-button").click(function(t){if(t.preventDefault(),void 0!==wp.media){var a=e(this),n=e(this).data("frame");if(n)return n.open(),!1;n=wp.media({title:a.data("choose"),library:{type:a.data("library").split(",").map(function(e){return e.trim()})},button:{text:a.data("update"),close:!1}}),a.data("frame",n),n.on("select",function(){var e=n.state().get("selection").first().attributes;i.find(".current .title").html(e.title),s.val(e.id),s.trigger("change",{silent:!0});var t=i.find(".current .thumbnail");void 0!==e.sizes?void 0!==e.sizes.thumbnail?t.attr("src",e.sizes.thumbnail.url).fadeIn():t.attr("src",e.sizes.full.url).fadeIn():t.attr("src",e.icon).fadeIn(),i.find(".media-remove-button").removeClass("remove-hide"),n.close()}),n.open()}}),a.find(".current").mouseenter(function(){var t=e(this).find(".title");""!==t.html()&&t.fadeIn("fast")}).mouseleave(function(){e(this).find(".title").clearQueue().fadeOut("fast")}),i.find("a.media-remove-button").click(function(t){t.preventDefault(),i.find(".current .title").html(""),s.val(""),i.find(".current .thumbnail").fadeOut("fast"),e(this).addClass("remove-hide")});var n,r=function(){if(n){var e=n.find(".so-widgets-image-results");if(0!==e.length){var t=e.width(),i=Math.floor(t/276),a=t-276*i,s=a/i+260;e.find(".so-widgets-result-image").css({width:s,height:s/1.4})}}};e(window).resize(r);var o=function(){if(!n){n=e(e("#so-widgets-bundle-tpl-image-search-dialog").html().trim()).appendTo("body"),n.find(".close").click(function(){n.hide()});var t=n.find(".so-widgets-image-results"),a=function(i,a){n.find(".so-widgets-results-loading").fadeIn("fast"),n.find(".so-widgets-results-loading strong").html(n.find(".so-widgets-results-loading strong").data("loading")),n.find(".so-widgets-results-more").hide(),e.get(ajaxurl,{action:"so_widgets_image_search",q:i,page:a,_sononce:n.find('input[name="_sononce"]').val()},function(s){if(s.error)return void alert(s.message);t.removeClass("so-loading"),e.each(s.items,function(i,a){var s=e(e("#so-widgets-bundle-tpl-image-search-result").html().trim()).appendTo(t).addClass("source-"+a.source),n=s.find(".so-widgets-result-image");n.css("background-image","url("+a.thumbnail+")"),n.data("thumbnail",a.thumbnail),n.data("preview",a.preview),a.url&&n.attr({href:a.url,target:"_blank"}),a.full_url&&(n.data({full_url:a.full_url,import_signature:a.import_signature}),n.attr("href",a.full_url)),"shutterstock"===a.source&&n.append(e("#so-widgets-bundle-tpl-image-search-result-sponsored").html())}),1===a&&(n.find("#so-widgets-image-search-suggestions ul").empty(),e.each(s.keywords,function(t,i){n.find("#so-widgets-image-search-suggestions").show(),n.find("#so-widgets-image-search-suggestions ul").append(e("<li></li>").append(e('<a href="#"></a>').html(i).data("keyword",i)))})),n.find(".so-widgets-results-loading").fadeOut("fast"),r(),n.find(".so-widgets-results-more").show().find("button").data({query:i,page:a+1})})};n.find("#so-widgets-image-search-form").submit(function(e){e.preventDefault();var i=n.find(".so-widgets-search-input").val();t.empty(),""!==i&&a(i,1)}),n.on("click",".so-keywords-list a",function(t){t.preventDefault();var i=e(this).blur();n.find(".so-widgets-search-input").val(i.data("keyword")),n.find("#so-widgets-image-search-form").submit()}),n.find(".so-widgets-results-more button").click(function(){var t=e(this);a(t.data("query"),t.data("page"))});var o;n.on("click",".so-widgets-result-image",function(t){var a=e(this);if(a.data("full_url")&&(t.preventDefault(),confirm(n.data("confirm-import")))){n.addClass("so-widgets-importing");var r=e("#post_ID").val();null===r&&(r=""),e.get(ajaxurl,{action:"so_widgets_image_import",full_url:a.data("full_url"),import_signature:a.data("import_signature"),post_id:r,_sononce:n.find('input[name="_sononce"]').val()},function(e){n.find("#so-widgets-image-search-frame").removeClass("so-widgets-importing"),!1===e.error?(n.hide(),n.find(".so-widgets-results-loading").hide(),s.val(e.attachment_id).trigger("change",{silent:!0}),i.find(".current .thumbnail").attr("src",e.thumb).fadeIn(),i.find(".media-remove-button").removeClass("remove-hide")):(alert(e.message),n.find(".so-widgets-results-loading").hide())}),n.find(".so-widgets-results-loading").fadeIn("fast"),n.find(".so-widgets-results-loading strong").html(n.find(".so-widgets-results-loading strong").data("importing")),n.find(".so-widgets-results-more").hide(),n.find("#so-widgets-image-search-frame").addClass("so-widgets-importing")}});var d=n.find(".so-widgets-preview-window");n.on("mouseenter",".so-widgets-result-image",function(){var t=e(this),i=t.data("preview");clearTimeout(o),o=setTimeout(function(){var a=1,s=1;i[1]>.33*e(window).outerWidth()&&(a=.33*e(window).outerWidth()/i[1]),i[2]>.5*e(window).outerHeight()&&(s=.5*e(window).outerHeight()/i[2]);var r=Math.min(a,s);r>1&&(r=1),d.show().find(".so-widgets-preview-window-inside").css({"background-image":"url("+t.data("thumbnail")+")",width:i[1]*r,height:i[2]*r}).append(e("<img />").attr("src",i[0])),n.trigger("mousemove")},1e3)}).on("mouseleave",".so-widgets-result-image",function(){d.hide().find("img").remove(),clearTimeout(o)});var l,u;n.on("mousemove",function(t){if(t.clientX&&(l=t.clientX),t.clientY&&(u=t.clientY),d.is(":visible")){var i=d.outerHeight(),a=d.outerWidth(),s=e(window).outerHeight(),n=e(window).outerWidth(),r=u-i/2;r=Math.max(r,10),r=Math.min(r,s-10-i);var o=l<n/2?l+15:l-15-a;d.css({top:r,left:o})}})}n.show(),n.find(".so-widgets-search-input").focus()};a.find(".find-image-button").click(function(e){e.preventDefault(),o()}),s.change(function(e,t){if(!t||!t.silent){var a=s.val();if(a){var n=i.find(".current .thumbnail"),r=wp.media.attachment(a);r.fetch().done(function(){if(r.has("sizes")){var e=r.get("sizes");void 0!==e.thumbnail?n.attr("src",e.thumbnail.url).fadeIn():n.attr("src",e.full.url).fadeIn()}else n.attr("src",r.get("icon")).fadeIn();i.find(".media-remove-button").removeClass("remove-hide")})}else i.find("a.media-remove-button").click()}}),a.data("initialized",!0)}})}(jQuery);
1
+ !function(e){e(document).on("sowsetupformfield",".siteorigin-widget-field-type-media",function(t){var i=e(this),a=i.find("> .media-field-wrapper"),s=i.find(".siteorigin-widget-input").not(".media-fallback-external");if(!a.data("initialized")){a.find(".media-upload-button").click(function(t){if(t.preventDefault(),void 0!==wp.media){var a=e(this),n=e(this).data("frame");if(n)return n.open(),!1;n=wp.media({title:a.data("choose"),library:{type:a.data("library").split(",").map(function(e){return e.trim()})},button:{text:a.data("update"),close:!1}}),a.data("frame",n),n.on("select",function(){var e=n.state().get("selection").first().attributes;i.find(".current .title").html(e.title),s.val(e.id),s.trigger("change",{silent:!0});var t=i.find(".current .thumbnail");void 0!==e.sizes?void 0!==e.sizes.thumbnail?t.attr("src",e.sizes.thumbnail.url).fadeIn():t.attr("src",e.sizes.full.url).fadeIn():t.attr("src",e.icon).fadeIn(),i.find(".media-remove-button").removeClass("remove-hide"),n.close()}),n.open()}}),a.find(".current").mouseenter(function(){var t=e(this).find(".title");""!==t.html()&&t.fadeIn("fast")}).mouseleave(function(){e(this).find(".title").clearQueue().fadeOut("fast")}),i.find("a.media-remove-button").click(function(t){t.preventDefault(),i.find(".current .title").html(""),s.val(""),s.trigger("change",{silent:!0}),i.find(".current .thumbnail").fadeOut("fast"),e(this).addClass("remove-hide")});var n,r=function(){if(n){var e=n.find(".so-widgets-image-results");if(0!==e.length){var t=e.width(),i=Math.floor(t/276),a=t-276*i,s=a/i+260;e.find(".so-widgets-result-image").css({width:s,height:s/1.4})}}};e(window).resize(r);var o=function(){if(!n){n=e(e("#so-widgets-bundle-tpl-image-search-dialog").html().trim()).appendTo("body"),n.find(".close").click(function(){n.hide()});var t=n.find(".so-widgets-image-results"),a=function(i,a){n.find(".so-widgets-results-loading").fadeIn("fast"),n.find(".so-widgets-results-loading strong").html(n.find(".so-widgets-results-loading strong").data("loading")),n.find(".so-widgets-results-more").hide(),e.get(ajaxurl,{action:"so_widgets_image_search",q:i,page:a,_sononce:n.find('input[name="_sononce"]').val()},function(s){if(s.error)return void alert(s.message);t.removeClass("so-loading"),e.each(s.items,function(i,a){var s=e(e("#so-widgets-bundle-tpl-image-search-result").html().trim()).appendTo(t).addClass("source-"+a.source),n=s.find(".so-widgets-result-image");n.css("background-image","url("+a.thumbnail+")"),n.data("thumbnail",a.thumbnail),n.data("preview",a.preview),a.url&&n.attr({href:a.url,target:"_blank"}),a.full_url&&(n.data({full_url:a.full_url,import_signature:a.import_signature}),n.attr("href",a.full_url)),"shutterstock"===a.source&&n.append(e("#so-widgets-bundle-tpl-image-search-result-sponsored").html())}),1===a&&(n.find("#so-widgets-image-search-suggestions ul").empty(),e.each(s.keywords,function(t,i){n.find("#so-widgets-image-search-suggestions").show(),n.find("#so-widgets-image-search-suggestions ul").append(e("<li></li>").append(e('<a href="#"></a>').html(i).data("keyword",i)))})),n.find(".so-widgets-results-loading").fadeOut("fast"),r(),n.find(".so-widgets-results-more").show().find("button").data({query:i,page:a+1})})};n.find("#so-widgets-image-search-form").submit(function(e){e.preventDefault();var i=n.find(".so-widgets-search-input").val();t.empty(),""!==i&&a(i,1)}),n.on("click",".so-keywords-list a",function(t){t.preventDefault();var i=e(this).blur();n.find(".so-widgets-search-input").val(i.data("keyword")),n.find("#so-widgets-image-search-form").submit()}),n.find(".so-widgets-results-more button").click(function(){var t=e(this);a(t.data("query"),t.data("page"))});var o;n.on("click",".so-widgets-result-image",function(t){var a=e(this);if(a.data("full_url")&&(t.preventDefault(),confirm(n.data("confirm-import")))){n.addClass("so-widgets-importing");var r=e("#post_ID").val();null===r&&(r=""),e.get(ajaxurl,{action:"so_widgets_image_import",full_url:a.data("full_url"),import_signature:a.data("import_signature"),post_id:r,_sononce:n.find('input[name="_sononce"]').val()},function(e){n.find("#so-widgets-image-search-frame").removeClass("so-widgets-importing"),!1===e.error?(n.hide(),n.find(".so-widgets-results-loading").hide(),s.val(e.attachment_id).trigger("change",{silent:!0}),i.find(".current .thumbnail").attr("src",e.thumb).fadeIn(),i.find(".media-remove-button").removeClass("remove-hide")):(alert(e.message),n.find(".so-widgets-results-loading").hide())}),n.find(".so-widgets-results-loading").fadeIn("fast"),n.find(".so-widgets-results-loading strong").html(n.find(".so-widgets-results-loading strong").data("importing")),n.find(".so-widgets-results-more").hide(),n.find("#so-widgets-image-search-frame").addClass("so-widgets-importing")}});var d=n.find(".so-widgets-preview-window");n.on("mouseenter",".so-widgets-result-image",function(){var t=e(this),i=t.data("preview");clearTimeout(o),o=setTimeout(function(){var a=1,s=1;i[1]>.33*e(window).outerWidth()&&(a=.33*e(window).outerWidth()/i[1]),i[2]>.5*e(window).outerHeight()&&(s=.5*e(window).outerHeight()/i[2]);var r=Math.min(a,s);r>1&&(r=1),d.show().find(".so-widgets-preview-window-inside").css({"background-image":"url("+t.data("thumbnail")+")",width:i[1]*r,height:i[2]*r}).append(e("<img />").attr("src",i[0])),n.trigger("mousemove")},1e3)}).on("mouseleave",".so-widgets-result-image",function(){d.hide().find("img").remove(),clearTimeout(o)});var l,u;n.on("mousemove",function(t){if(t.clientX&&(l=t.clientX),t.clientY&&(u=t.clientY),d.is(":visible")){var i=d.outerHeight(),a=d.outerWidth(),s=e(window).outerHeight(),n=e(window).outerWidth(),r=u-i/2;r=Math.max(r,10),r=Math.min(r,s-10-i);var o=l<n/2?l+15:l-15-a;d.css({top:r,left:o})}})}n.show(),n.find(".so-widgets-search-input").focus()};a.find(".find-image-button").click(function(e){e.preventDefault(),o()}),s.change(function(e,t){if(!t||!t.silent){var a=s.val();if(a){var n=i.find(".current .thumbnail"),r=wp.media.attachment(a);r.fetch().done(function(){if(r.has("sizes")){var e=r.get("sizes");void 0!==e.thumbnail?n.attr("src",e.thumbnail.url).fadeIn():n.attr("src",e.full.url).fadeIn()}else n.attr("src",r.get("icon")).fadeIn();i.find(".media-remove-button").removeClass("remove-hide")})}else i.find("a.media-remove-button").click()}}),a.data("initialized",!0)}})}(jQuery);
base/inc/fields/tinymce.class.php CHANGED
@@ -64,6 +64,13 @@ class SiteOrigin_Widget_Field_TinyMCE extends SiteOrigin_Widget_Field_Text_Input
64
  * @var array
65
  */
66
  protected $quicktags_buttons;
 
 
 
 
 
 
 
67
  /**
68
  * An array of filter callbacks to apply to the set of buttons which will be rendered for the editor.
69
  *
@@ -93,8 +100,17 @@ class SiteOrigin_Widget_Field_TinyMCE extends SiteOrigin_Widget_Field_Text_Input
93
  */
94
  private $wp_version_lt_4_8;
95
 
 
 
 
 
 
 
 
 
96
  protected function get_default_options() {
97
  return array(
 
98
  'mce_buttons' => array(
99
  'formatselect',
100
  'bold',
@@ -372,7 +388,7 @@ class SiteOrigin_Widget_Field_TinyMCE extends SiteOrigin_Widget_Field_Text_Input
372
  'tinymce' => array(
373
  'wp_skip_init' => strpos( $this->element_id, '__i__' ) != false ||
374
  strpos( $this->element_id, '_id_' ) != false,
375
- 'wpautop' => true,
376
  ),
377
  'quicktags' => array(
378
  'buttons' => $qt_settings['buttons'],
@@ -480,6 +496,9 @@ class SiteOrigin_Widget_Field_TinyMCE extends SiteOrigin_Widget_Field_Text_Input
480
  }
481
 
482
  protected function sanitize_field_input( $value, $instance ) {
 
 
 
483
  if( current_user_can( 'unfiltered_html' ) ) {
484
  $sanitized_value = $value;
485
  } else {
64
  * @var array
65
  */
66
  protected $quicktags_buttons;
67
+ /**
68
+ * Whether to apply `wpautop` processing. (Adds paragraphs for double linebreaks) Default is true.
69
+ *
70
+ * @access protected
71
+ * @var array
72
+ */
73
+ protected $wpautop;
74
  /**
75
  * An array of filter callbacks to apply to the set of buttons which will be rendered for the editor.
76
  *
100
  */
101
  private $wp_version_lt_4_8;
102
 
103
+ public static function unautop( $text ) {
104
+ $text = str_replace('<p>', '', $text);
105
+ $text = str_replace(array('<br />', '<br>', '<br/>'), "\n", $text);
106
+ $text = str_replace('</p>', "\n\n", $text);
107
+
108
+ return $text;
109
+ }
110
+
111
  protected function get_default_options() {
112
  return array(
113
+ 'wpautop' => true,
114
  'mce_buttons' => array(
115
  'formatselect',
116
  'bold',
388
  'tinymce' => array(
389
  'wp_skip_init' => strpos( $this->element_id, '__i__' ) != false ||
390
  strpos( $this->element_id, '_id_' ) != false,
391
+ 'wpautop' => ! empty( $this->wpautop ),
392
  ),
393
  'quicktags' => array(
394
  'buttons' => $qt_settings['buttons'],
496
  }
497
 
498
  protected function sanitize_field_input( $value, $instance ) {
499
+ if ( ! empty( $this->wpautop ) ) {
500
+ $value = wpautop( self::unautop( $value ) );
501
+ }
502
  if( current_user_can( 'unfiltered_html' ) ) {
503
  $sanitized_value = $value;
504
  } else {
base/inc/less-functions.php CHANGED
@@ -1,41 +1,41 @@
1
- <?php
2
-
3
- /**
4
- * Class siteorigin_lessc
5
- *
6
- * An extension to the lessc class that adds a few custom functions
7
- */
8
- class SiteOrigin_Widgets_Less_Functions {
9
-
10
- private $widget;
11
- private $widget_instance;
12
-
13
- function __construct($widget, $widget_instance){
14
- $this->widget = $widget;
15
- $this->widget_instance = $widget_instance;
16
- }
17
-
18
- /**
19
- * @param lessc $c
20
- *
21
- * Register less functions in a lessc object
22
- */
23
- function registerFunctions(&$c){
24
- if( method_exists( $c, 'registerFunction' ) ) {
25
- $c->registerFunction( 'length', array($this, 'length') );
26
- }
27
- }
28
-
29
- /**
30
- * Very basic length function that checks the length of a list. Might need some more checks for other types.
31
- *
32
- * @param $arg
33
- *
34
- * @return int
35
- */
36
- function length($arg){
37
- if(empty($arg[0]) || empty($arg[2]) || $arg[0] != 'list') return 1;
38
- return count($arg[2]);
39
- }
40
-
41
- }
1
+ <?php
2
+
3
+ /**
4
+ * Class siteorigin_lessc
5
+ *
6
+ * An extension to the SiteOrigin_LessC class that adds a few custom functions
7
+ */
8
+ class SiteOrigin_Widgets_Less_Functions {
9
+
10
+ private $widget;
11
+ private $widget_instance;
12
+
13
+ function __construct($widget, $widget_instance){
14
+ $this->widget = $widget;
15
+ $this->widget_instance = $widget_instance;
16
+ }
17
+
18
+ /**
19
+ * @param SiteOrigin_LessC $c
20
+ *
21
+ * Register less functions in a SiteOrigin_LessC object
22
+ */
23
+ function registerFunctions(&$c){
24
+ if( method_exists( $c, 'registerFunction' ) ) {
25
+ $c->registerFunction( 'length', array($this, 'length') );
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Very basic length function that checks the length of a list. Might need some more checks for other types.
31
+ *
32
+ * @param $arg
33
+ *
34
+ * @return int
35
+ */
36
+ function length($arg){
37
+ if(empty($arg[0]) || empty($arg[2]) || $arg[0] != 'list') return 1;
38
+ return count($arg[2]);
39
+ }
40
+
41
+ }
base/inc/lessc.inc.php CHANGED
@@ -1,283 +1,283 @@
1
- <?php
2
- /**
3
- * This file provides the part of lessphp API (https://github.com/leafo/lessphp)
4
- * to be a drop-in replacement for following products:
5
- * - Drupal 7, by the less module v3.0+ (https://drupal.org/project/less)
6
- * - Symfony 2
7
- *
8
- * @SiteOrigin: We originally used leafo/lessphp (https://github.com/leafo/lessphp), until we found it wasn't
9
- * maintained and missed some newer LESS features. We then migrated to a more recent and maintained repo
10
- * (https://github.com/oyejorge/less.php) simply replacing leafo's lessc.inc.php with the one from oyejorge. This
11
- * worked well until users started running PHP 7 compatibility checkers which found some issues, so now we have our own
12
- * fork here: https://github.com/siteorigin/less.php We have fixed the PHP 7 compatibility issues and will only make
13
- * more changes if there are severe issues.
14
- */
15
-
16
- // Register autoloader for non-composer installations
17
- if ( !class_exists( 'Less_Parser' ) ) {
18
- require_once dirname( __FILE__ ) . '/lib/Less/Autoloader.php';
19
- Less_Autoloader::register();
20
- }
21
-
22
- class lessc {
23
-
24
- static public $VERSION = Less_Version::less_version;
25
-
26
- public $importDir = '';
27
- protected $allParsedFiles = array();
28
- protected $libFunctions = array();
29
- protected $registeredVars = array();
30
- private $formatterName;
31
- private $options = array();
32
-
33
- public function __construct( $lessc=null, $sourceName=null ) {}
34
-
35
- public function setImportDir( $dirs ) {
36
- $this->importDir = (array)$dirs;
37
- }
38
-
39
- public function addImportDir( $dir ) {
40
- $this->importDir = (array)$this->importDir;
41
- $this->importDir[] = $dir;
42
- }
43
-
44
- public function setFormatter( $name ) {
45
- $this->formatterName = $name;
46
- }
47
-
48
- public function setPreserveComments( $preserve ) {}
49
-
50
- public function registerFunction( $name, $func ) {
51
- $this->libFunctions[$name] = $func;
52
- }
53
-
54
- public function unregisterFunction( $name ) {
55
- unset( $this->libFunctions[$name] );
56
- }
57
-
58
- public function setVariables( $variables ){
59
- foreach ( $variables as $name => $value ) {
60
- $this->setVariable( $name, $value );
61
- }
62
- }
63
-
64
- public function setVariable( $name, $value ) {
65
- $this->registeredVars[$name] = $value;
66
- }
67
-
68
- public function unsetVariable( $name ) {
69
- unset( $this->registeredVars[$name] );
70
- }
71
-
72
- public function setOptions( $options ) {
73
- foreach ( $options as $name => $value ) {
74
- $this->setOption( $name, $value);
75
- }
76
- }
77
-
78
- public function setOption( $name, $value ) {
79
- $this->options[$name] = $value;
80
- }
81
-
82
- public function parse( $buffer, $presets = array() ) {
83
-
84
- $this->setVariables( $presets );
85
-
86
- $parser = new Less_Parser( $this->getOptions() );
87
- $parser->setImportDirs( $this->getImportDirs() );
88
- foreach ( $this->libFunctions as $name => $func ) {
89
- $parser->registerFunction( $name, $func );
90
- }
91
- $parser->parse($buffer);
92
- if ( count( $this->registeredVars ) ) {
93
- $parser->ModifyVars( $this->registeredVars );
94
- }
95
-
96
- return $parser->getCss();
97
- }
98
-
99
- protected function getOptions() {
100
- $options = array( 'relativeUrls'=>false );
101
- switch( $this->formatterName ) {
102
- case 'compressed':
103
- $options['compress'] = true;
104
- break;
105
- }
106
- if (is_array($this->options))
107
- {
108
- $options = array_merge($options, $this->options);
109
- }
110
- return $options;
111
- }
112
-
113
- protected function getImportDirs() {
114
- $dirs_ = (array)$this->importDir;
115
- $dirs = array();
116
- foreach ( $dirs_ as $dir ) {
117
- $dirs[$dir] = '';
118
- }
119
- return $dirs;
120
- }
121
-
122
- public function compile( $string, $name = null ) {
123
-
124
- $oldImport = $this->importDir;
125
- $this->importDir = (array)$this->importDir;
126
-
127
- $this->allParsedFiles = array();
128
-
129
- $parser = new Less_Parser( $this->getOptions() );
130
- $parser->SetImportDirs( $this->getImportDirs() );
131
- if ( count( $this->registeredVars ) ) {
132
- $parser->ModifyVars( $this->registeredVars );
133
- }
134
- foreach ( $this->libFunctions as $name => $func ) {
135
- $parser->registerFunction( $name, $func );
136
- }
137
- $parser->parse( $string );
138
- $out = $parser->getCss();
139
-
140
- $parsed = Less_Parser::AllParsedFiles();
141
- foreach ( $parsed as $file ) {
142
- $this->addParsedFile( $file );
143
- }
144
-
145
- $this->importDir = $oldImport;
146
-
147
- return $out;
148
- }
149
-
150
- public function compileFile( $fname, $outFname = null ) {
151
- if ( !is_readable( $fname ) ) {
152
- throw new Exception( 'load error: failed to find '.$fname );
153
- }
154
-
155
- $pi = pathinfo( $fname );
156
-
157
- $oldImport = $this->importDir;
158
-
159
- $this->importDir = (array)$this->importDir;
160
- $this->importDir[] = Less_Parser::AbsPath( $pi['dirname'] ).'/';
161
-
162
- $this->allParsedFiles = array();
163
- $this->addParsedFile( $fname );
164
-
165
- $parser = new Less_Parser( $this->getOptions() );
166
- $parser->SetImportDirs( $this->getImportDirs() );
167
- if ( count( $this->registeredVars ) ) {
168
- $parser->ModifyVars( $this->registeredVars );
169
- }
170
- foreach ( $this->libFunctions as $name => $func ) {
171
- $parser->registerFunction( $name, $func );
172
- }
173
- $parser->parseFile( $fname );
174
- $out = $parser->getCss();
175
-
176
- $parsed = Less_Parser::AllParsedFiles();
177
- foreach ( $parsed as $file ) {
178
- $this->addParsedFile( $file );
179
- }
180
-
181
- $this->importDir = $oldImport;
182
-
183
- if ( $outFname !== null ) {
184
- return file_put_contents( $outFname, $out );
185
- }
186
-
187
- return $out;
188
- }
189
-
190
- public function checkedCompile( $in, $out ) {
191
- if ( !is_file( $out ) || filemtime( $in ) > filemtime( $out ) ) {
192
- $this->compileFile($in, $out);
193
- return true;
194
- }
195
- return false;
196
- }
197
-
198
-
199
- /**
200
- * Execute lessphp on a .less file or a lessphp cache structure
201
- *
202
- * The lessphp cache structure contains information about a specific
203
- * less file having been parsed. It can be used as a hint for future
204
- * calls to determine whether or not a rebuild is required.
205
- *
206
- * The cache structure contains two important keys that may be used
207
- * externally:
208
- *
209
- * compiled: The final compiled CSS
210
- * updated: The time (in seconds) the CSS was last compiled
211
- *
212
- * The cache structure is a plain-ol' PHP associative array and can
213
- * be serialized and unserialized without a hitch.
214
- *
215
- * @param mixed $in Input
216
- * @param bool $force Force rebuild?
217
- * @return array lessphp cache structure
218
- */
219
- public function cachedCompile( $in, $force = false ) {
220
- // assume no root
221
- $root = null;
222
-
223
- if ( is_string( $in ) ) {
224
- $root = $in;
225
- } elseif ( is_array( $in ) and isset( $in['root'] ) ) {
226
- if ( $force or ! isset( $in['files'] ) ) {
227
- // If we are forcing a recompile or if for some reason the
228
- // structure does not contain any file information we should
229
- // specify the root to trigger a rebuild.
230
- $root = $in['root'];
231
- } elseif ( isset( $in['files'] ) and is_array( $in['files'] ) ) {
232
- foreach ( $in['files'] as $fname => $ftime ) {
233
- if ( !file_exists( $fname ) or filemtime( $fname ) > $ftime ) {
234
- // One of the files we knew about previously has changed
235
- // so we should look at our incoming root again.
236
- $root = $in['root'];
237
- break;
238
- }
239
- }
240
- }
241
- } else {
242
- // TODO: Throw an exception? We got neither a string nor something
243
- // that looks like a compatible lessphp cache structure.
244
- return null;
245
- }
246
-
247
- if ( $root !== null ) {
248
- // If we have a root value which means we should rebuild.
249
- $out = array();
250
- $out['root'] = $root;
251
- $out['compiled'] = $this->compileFile($root);
252
- $out['files'] = $this->allParsedFiles();
253
- $out['updated'] = time();
254
- return $out;
255
- } else {
256
- // No changes, pass back the structure
257
- // we were given initially.
258
- return $in;
259
- }
260
- }
261
-
262
- public function ccompile( $in, $out, $less = null ) {
263
- if ( $less === null ) {
264
- $less = new self;
265
- }
266
- return $less->checkedCompile( $in, $out );
267
- }
268
-
269
- public static function cexecute( $in, $force = false, $less = null ) {
270
- if ( $less === null ) {
271
- $less = new self;
272
- }
273
- return $less->cachedCompile($in, $force);
274
- }
275
-
276
- public function allParsedFiles() {
277
- return $this->allParsedFiles;
278
- }
279
-
280
- protected function addParsedFile( $file ) {
281
- $this->allParsedFiles[Less_Parser::AbsPath( $file )] = filemtime( $file );
282
- }
283
- }
1
+ <?php
2
+ /**
3
+ * This file provides the part of lessphp API (https://github.com/leafo/lessphp)
4
+ * to be a drop-in replacement for following products:
5
+ * - Drupal 7, by the less module v3.0+ (https://drupal.org/project/less)
6
+ * - Symfony 2
7
+ *
8
+ * @SiteOrigin: We originally used leafo/lessphp (https://github.com/leafo/lessphp), until we found it wasn't
9
+ * maintained and missed some newer LESS features. We then migrated to a more recent and maintained repo
10
+ * (https://github.com/oyejorge/less.php) simply replacing leafo's lessc.inc.php with the one from oyejorge. This
11
+ * worked well until users started running PHP 7 compatibility checkers which found some issues, so now we have our own
12
+ * fork here: https://github.com/siteorigin/less.php We have fixed the PHP 7 compatibility issues and will only make
13
+ * more changes if there are severe issues.
14
+ */
15
+
16
+ // Register autoloader for non-composer installations
17
+ if ( !class_exists( 'Less_Parser' ) ) {
18
+ require_once dirname( __FILE__ ) . '/lib/Less/Autoloader.php';
19
+ Less_Autoloader::register();
20
+ }
21
+
22
+ class SiteOrigin_LessC {
23
+
24
+ static public $VERSION = Less_Version::less_version;
25
+
26
+ public $importDir = '';
27
+ protected $allParsedFiles = array();
28
+ protected $libFunctions = array();
29
+ protected $registeredVars = array();
30
+ private $formatterName;
31
+ private $options = array();
32
+
33
+ public function __construct( $lessc=null, $sourceName=null ) {}
34
+
35
+ public function setImportDir( $dirs ) {
36
+ $this->importDir = (array)$dirs;
37
+ }
38
+
39
+ public function addImportDir( $dir ) {
40
+ $this->importDir = (array)$this->importDir;
41
+ $this->importDir[] = $dir;
42
+ }
43
+
44
+ public function setFormatter( $name ) {
45
+ $this->formatterName = $name;
46
+ }
47
+
48
+ public function setPreserveComments( $preserve ) {}
49
+
50
+ public function registerFunction( $name, $func ) {
51
+ $this->libFunctions[$name] = $func;
52
+ }
53
+
54
+ public function unregisterFunction( $name ) {
55
+ unset( $this->libFunctions[$name] );
56
+ }
57
+
58
+ public function setVariables( $variables ){
59
+ foreach ( $variables as $name => $value ) {
60
+ $this->setVariable( $name, $value );
61
+ }
62
+ }
63
+
64
+ public function setVariable( $name, $value ) {
65
+ $this->registeredVars[$name] = $value;
66
+ }
67
+
68
+ public function unsetVariable( $name ) {
69
+ unset( $this->registeredVars[$name] );
70
+ }
71
+
72
+ public function setOptions( $options ) {
73
+ foreach ( $options as $name => $value ) {
74
+ $this->setOption( $name, $value);
75
+ }
76
+ }
77
+
78
+ public function setOption( $name, $value ) {
79
+ $this->options[$name] = $value;
80
+ }
81
+
82
+ public function parse( $buffer, $presets = array() ) {
83
+
84
+ $this->setVariables( $presets );
85
+
86
+ $parser = new Less_Parser( $this->getOptions() );
87
+ $parser->setImportDirs( $this->getImportDirs() );
88
+ foreach ( $this->libFunctions as $name => $func ) {
89
+ $parser->registerFunction( $name, $func );
90
+ }
91
+ $parser->parse($buffer);
92
+ if ( count( $this->registeredVars ) ) {
93
+ $parser->ModifyVars( $this->registeredVars );
94
+ }
95
+
96
+ return $parser->getCss();
97
+ }
98
+
99
+ protected function getOptions() {
100
+ $options = array( 'relativeUrls'=>false );
101
+ switch( $this->formatterName ) {
102
+ case 'compressed':
103
+ $options['compress'] = true;
104
+ break;
105
+ }
106
+ if (is_array($this->options))
107
+ {
108
+ $options = array_merge($options, $this->options);
109
+ }
110
+ return $options;
111
+ }
112
+
113
+ protected function getImportDirs() {
114
+ $dirs_ = (array)$this->importDir;
115
+ $dirs = array();
116
+ foreach ( $dirs_ as $dir ) {
117
+ $dirs[$dir] = '';
118
+ }
119
+ return $dirs;
120
+ }
121
+
122
+ public function compile( $string, $name = null ) {
123
+
124
+ $oldImport = $this->importDir;
125
+ $this->importDir = (array)$this->importDir;
126
+
127
+ $this->allParsedFiles = array();
128
+
129
+ $parser = new Less_Parser( $this->getOptions() );
130
+ $parser->SetImportDirs( $this->getImportDirs() );
131
+ if ( count( $this->registeredVars ) ) {
132
+ $parser->ModifyVars( $this->registeredVars );
133
+ }
134
+ foreach ( $this->libFunctions as $name => $func ) {
135
+ $parser->registerFunction( $name, $func );
136
+ }
137
+ $parser->parse( $string );
138
+ $out = $parser->getCss();
139
+
140
+ $parsed = Less_Parser::AllParsedFiles();
141
+ foreach ( $parsed as $file ) {
142
+ $this->addParsedFile( $file );
143
+ }
144
+
145
+ $this->importDir = $oldImport;
146
+
147
+ return $out;
148
+ }
149
+
150
+ public function compileFile( $fname, $outFname = null ) {
151
+ if ( !is_readable( $fname ) ) {
152
+ throw new Exception( 'load error: failed to find '.$fname );
153
+ }
154
+
155
+ $pi = pathinfo( $fname );
156
+
157
+ $oldImport = $this->importDir;
158
+
159
+ $this->importDir = (array)$this->importDir;
160
+ $this->importDir[] = Less_Parser::AbsPath( $pi['dirname'] ).'/';
161
+
162
+ $this->allParsedFiles = array();
163
+ $this->addParsedFile( $fname );
164
+
165
+ $parser = new Less_Parser( $this->getOptions() );
166
+ $parser->SetImportDirs( $this->getImportDirs() );
167
+ if ( count( $this->registeredVars ) ) {
168
+ $parser->ModifyVars( $this->registeredVars );
169
+ }
170
+ foreach ( $this->libFunctions as $name => $func ) {
171
+ $parser->registerFunction( $name, $func );
172
+ }
173
+ $parser->parseFile( $fname );
174
+ $out = $parser->getCss();
175
+
176
+ $parsed = Less_Parser::AllParsedFiles();
177
+ foreach ( $parsed as $file ) {
178
+ $this->addParsedFile( $file );
179
+ }
180
+
181
+ $this->importDir = $oldImport;
182
+
183
+ if ( $outFname !== null ) {
184
+ return file_put_contents( $outFname, $out );
185
+ }
186
+
187
+ return $out;
188
+ }
189
+
190
+ public function checkedCompile( $in, $out ) {
191
+ if ( !is_file( $out ) || filemtime( $in ) > filemtime( $out ) ) {
192
+ $this->compileFile($in, $out);
193
+ return true;
194
+ }
195
+ return false;
196
+ }
197
+
198
+
199
+ /**
200
+ * Execute lessphp on a .less file or a lessphp cache structure
201
+ *
202
+ * The lessphp cache structure contains information about a specific
203
+ * less file having been parsed. It can be used as a hint for future
204
+ * calls to determine whether or not a rebuild is required.
205
+ *
206
+ * The cache structure contains two important keys that may be used
207
+ * externally:
208
+ *
209
+ * compiled: The final compiled CSS
210
+ * updated: The time (in seconds) the CSS was last compiled
211
+ *
212
+ * The cache structure is a plain-ol' PHP associative array and can
213
+ * be serialized and unserialized without a hitch.
214
+ *
215
+ * @param mixed $in Input
216
+ * @param bool $force Force rebuild?
217
+ * @return array lessphp cache structure
218
+ */
219
+ public function cachedCompile( $in, $force = false ) {
220
+ // assume no root
221
+ $root = null;
222
+
223
+ if ( is_string( $in ) ) {
224
+ $root = $in;
225
+ } elseif ( is_array( $in ) and isset( $in['root'] ) ) {
226
+ if ( $force or ! isset( $in['files'] ) ) {
227
+ // If we are forcing a recompile or if for some reason the
228
+ // structure does not contain any file information we should
229
+ // specify the root to trigger a rebuild.
230
+ $root = $in['root'];
231
+ } elseif ( isset( $in['files'] ) and is_array( $in['files'] ) ) {
232
+ foreach ( $in['files'] as $fname => $ftime ) {
233
+ if ( !file_exists( $fname ) or filemtime( $fname ) > $ftime ) {
234
+ // One of the files we knew about previously has changed
235
+ // so we should look at our incoming root again.
236
+ $root = $in['root'];
237
+ break;
238
+ }
239
+ }
240
+ }
241
+ } else {
242
+ // TODO: Throw an exception? We got neither a string nor something
243
+ // that looks like a compatible lessphp cache structure.
244
+ return null;
245
+ }
246
+
247
+ if ( $root !== null ) {
248
+ // If we have a root value which means we should rebuild.
249
+ $out = array();
250
+ $out['root'] = $root;
251
+ $out['compiled'] = $this->compileFile($root);
252
+ $out['files'] = $this->allParsedFiles();
253
+ $out['updated'] = time();
254
+ return $out;
255
+ } else {
256
+ // No changes, pass back the structure
257
+ // we were given initially.
258
+ return $in;
259
+ }
260
+ }
261
+
262
+ public function ccompile( $in, $out, $less = null ) {
263
+ if ( $less === null ) {
264
+ $less = new self;
265
+ }
266
+ return $less->checkedCompile( $in, $out );
267
+ }
268
+
269
+ public static function cexecute( $in, $force = false, $less = null ) {
270
+ if ( $less === null ) {
271
+ $less = new self;
272
+ }
273
+ return $less->cachedCompile($in, $force);
274
+ }
275
+
276
+ public function allParsedFiles() {
277
+ return $this->allParsedFiles;
278
+ }
279
+
280
+ protected function addParsedFile( $file ) {
281
+ $this->allParsedFiles[Less_Parser::AbsPath( $file )] = filemtime( $file );
282
+ }
283
+ }
base/inc/widgets/base-slider.class.php CHANGED
@@ -172,18 +172,18 @@ abstract class SiteOrigin_Widget_Base_Slider extends SiteOrigin_Widget {
172
  ?>
173
  <ol class="sow-slider-pagination">
174
  <?php foreach($frames as $i => $frame) : ?>
175
- <li><a href="#" data-goto="<?php echo $i ?>"><?php echo $i+1 ?></a></li>
176
  <?php endforeach; ?>
177
  </ol>
178
 
179
  <div class="sow-slide-nav sow-slide-nav-next">
180
- <a href="#" data-goto="next" data-action="next">
181
  <em class="sow-sld-icon-<?php echo sanitize_html_class( $controls['nav_style'] ) ?>-right"></em>
182
  </a>
183
  </div>
184
 
185
  <div class="sow-slide-nav sow-slide-nav-prev">
186
- <a href="#" data-goto="previous" data-action="prev">
187
  <em class="sow-sld-icon-<?php echo sanitize_html_class( $controls['nav_style'] ) ?>-left"></em>
188
  </a>
189
  </div>
172
  ?>
173
  <ol class="sow-slider-pagination">
174
  <?php foreach($frames as $i => $frame) : ?>
175
+ <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>
176
  <?php endforeach; ?>
177
  </ol>
178
 
179
  <div class="sow-slide-nav sow-slide-nav-next">
180
+ <a href="#" data-goto="next" aria-label="<?php _e( 'next slide', 'so-widgets-bundle' ) ?>" data-action="next">
181
  <em class="sow-sld-icon-<?php echo sanitize_html_class( $controls['nav_style'] ) ?>-right"></em>
182
  </a>
183
  </div>
184
 
185
  <div class="sow-slide-nav sow-slide-nav-prev">
186
+ <a href="#" data-goto="previous" aria-label="<?php _e( 'previous slide', 'so-widgets-bundle' ) ?>" data-action="prev">
187
  <em class="sow-sld-icon-<?php echo sanitize_html_class( $controls['nav_style'] ) ?>-left"></em>
188
  </a>
189
  </div>
base/js/admin.js CHANGED
@@ -449,12 +449,14 @@ var sowbForms = window.sowbForms || {};
449
  };
450
 
451
  $fields.filter('[data-state-emitter]').each(function () {
452
-
 
 
453
  // Listen for any change events on an emitter field
454
- $(this).find('.siteorigin-widget-input').on('keyup change', stateEmitterChangeHandler);
455
 
456
  // Trigger initial state emitter changes
457
- $(this).find('.siteorigin-widget-input').each(function () {
458
  var $$ = $(this);
459
  if ($$.is(':radio')) {
460
  // Only checked radio inputs must have change events
449
  };
450
 
451
  $fields.filter('[data-state-emitter]').each(function () {
452
+
453
+ var $input = $( this ).find( '.siteorigin-widget-input' );
454
+
455
  // Listen for any change events on an emitter field
456
+ $input.on('keyup change', stateEmitterChangeHandler);
457
 
458
  // Trigger initial state emitter changes
459
+ $input.each(function () {
460
  var $$ = $(this);
461
  if ($$.is(':radio')) {
462
  // Only checked radio inputs must have change events
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=e(this),n=e.extend({},i.data("state-handler"),a?i.data("state-handler-initial"):{});if(0===Object.keys(n).length)return!0;var s,o,d,l,g,f,c={},p=sowbForms.getContainerFieldId(i,"repeater",".siteorigin-widget-field-repeater-item");if(!1!==p){var u={};for(var m in n)u[m.replace("{$repeater}",p)]=n[m];n=u}var w=sowbForms.getContainerFieldId(i,"widget",".siteorigin-widget-widget");if(!1!==w){var v={};for(var h in n){var b=h.match(/_else\[(.*)\]|(.*)\[(.*)\]/),y="";y=b&&b.length&&void 0===b[1]?b[2]+"_"+w+"["+b[3]+"]":"_else["+b[1]+"_"+w+"]",v[y]=n[h]}n=v}for(var F in n)if(g=!1,null!==(s=F.match(/^([a-zA-Z0-9_-]+)(\[([a-zA-Z0-9_\-,]+)\])?(\[\])?$/))){if(o={group:"default",name:"",multi:!1},void 0!==s[2]?(o.group=s[1],o.name=s[3]):o.name=s[0],o.multi=void 0!==s[4],"_else"===o.group)o.group=o.name,o.name="",g=o.group===t&&void 0===c[o.group];else{f=o.name.split(",").map(function(e){return e.trim()});for(var k=0;k<f.length&&!(g=o.group===t&&f[k]===r);k++);}if(g){d=n[F],o.multi||(d=[d]);for(var k=0;k<d.length;k++)l=void 0!==d[k][1]&&Boolean(d[k][1])?i.find(d[k][1]):i,l[d[k][0]].apply(l,void 0!==d[k][2]?d[k][2]:[]);c[o.group]=!0}}})}),n.sowSetupPreview(),r=n;var d=n.find(".siteorigin-widget-teaser");d.find(".dashicons-dismiss").click(function(){var i=e(this);e.get(i.data("dismiss-url")),d.slideUp("normal",function(){d.remove()})});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));if(c)if(c._sow_form_timestamp>f){var p=e('<div class="siteorigin-widget-form-notification"><span>'+soWidgets.backup.newerVersion+'</span><a class="button button-small so-backup-restore">'+soWidgets.backup.restore+'</a><a class="button button-small so-backup-dismiss">'+soWidgets.backup.dismiss+"</a><div><small>"+soWidgets.backup.replaceWarning+"</small></div></div>");n.prepend(p),p.find(".so-backup-restore").click(function(){sowbForms.setWidgetFormValues(r,c),p.slideUp("fast",function(){p.remove()})}),p.find(".so-backup-dismiss").click(function(){p.slideUp("fast",function(){sessionStorage.removeItem(l),p.remove()})})}else 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 u=n.find("> .siteorigin-widget-field");u.find("> .siteorigin-widget-section").sowSetupForm();var m=u.find("> .siteorigin-widget-widget");m.find("> .siteorigin-widget-section").sowSetupForm(),m.filter(":not(:has(> .siteorigin-widget-section))").sowSetupForm(),u.find(".siteorigin-widget-input").each(function(i,t){null===e(t).data("original-name")&&e(t).data("original-name",e(t).attr("name"))}),u.find("> .siteorigin-widget-field-repeater").sowSetupRepeater(),n.find(".siteorigin-widget-field-repeater-item").sowSetupRepeaterItems(),u.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(){if(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")}})};u.filter(".siteorigin-widget-field-type-widget, .siteorigin-widget-field-type-section").find("> label").click(w),u.filter(".siteorigin-widget-field-type-posts").find(".posts-container-label-wrapper").click(w),u.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,i){t.val(parseFloat(i.value)),t.trigger("change")},change:function(e,t){i.find(".siteorigin-widget-slider-value").html(t.value)}}),t.change(function(e,i){i&&i.silent||r.slider("value",parseFloat(t.val()))})}),u.filter(".siteorigin-widget-field-type-link").each(function(){var i=e(this),t=null,r=function(){null!==t&&t.abort();var r=i.find(".content-text-search"),n=r.val(),a=r.data("postTypes"),s=i.find("ul.posts").empty().addClass("loading");e.get(soWidgets.ajaxurl,{action:"so_widgets_search_posts",query:n,postTypes:a},function(i){for(var t=0;t<i.length;t++)""===i[t].label&&(i[t].label="&nbsp;"),s.append(e("<li>").addClass("post").html(i[t].label+"<span>("+i[t].type+")</span>").data(i[t]));s.removeClass("loading")})};i.find(".select-content-button, .button-close").click(function(t){t.preventDefault(),e(this).blur();var n=i.find(".existing-content-selector");n.toggle(),n.is(":visible")&&0===n.find("ul.posts li").length&&r()}),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.find(".existing-content-selector").toggle()});var n=null;i.find(".content-text-search").keyup(function(){null!==n&&clearTimeout(n),n=setTimeout(function(){r()},500)})}),void 0!==jQuery.fn.soPanelsSetupBuilderWidget&&u.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 v=function(){var i=e(this),t=i.closest("[data-state-emitter]").data("state-emitter");if(void 0!==t){var n={default:""};void 0===t.length&&(t=[t]);for(var a=0;a<t.length;a++)n=function(t,r){if(void 0===sowEmitters[t.callback]||"_"===t.callback.substr(0,1))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+"_"+a}));var s=i.is('[type="checkbox"]')?i.is(":checked"):i.val();return e.extend(r,sowEmitters[t.callback](s,t.args))}(t[a],n);var s=r.data("states");void 0===s&&(s={default:""});for(var o in n)void 0!==s[o]&&n[o]===s[o]||(s[o]=n[o],r.trigger("sowstatechange",[o,n[o]]));r.data("states",s)}};u.filter("[data-state-emitter]").each(function(){e(this).find(".siteorigin-widget-input").on("keyup change",v),e(this).find(".siteorigin-widget-input").each(function(){var i=e(this);i.is(":radio")?i.is(":checked")&&v.call(i[0]):v.call(i[0])})}),n.trigger("sowsetupform",u).data("sow-form-setup",!0),u.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){if(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")});else{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.html().replace(/_id_/g,n),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(){if(e(window).resize(),e(this).is(":visible")){e(this).trigger("slideToggleOpenComplete");e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")}else e(this).trigger("slideToggleCloseComplete")}))}),a.find(".siteorigin-widget-field-remove").click(function(i,t){i.preventDefault();var n=e(this).closest(".siteorigin-widget-field-repeater-items"),a=e(this).closest(".siteorigin-widget-field-repeater-item"),s=function(){a.remove(),n.sortable("refresh").trigger("updateFieldPositions"),e(window).resize()};t&&t.silent?s():confirm(soWidgets.sure)&&a.slideUp("fast",s),r.trigger("change")}),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,m,w;if(i.is('[type="radio"]')){m=s.replace(/-\d+-\d+$/,"");var v=s.replace(/-\d+$/,"");if(!d[m]){var h={};d[m]=t.find(".siteorigin-widget-input[id^="+m+"]").not("[id*=_id_]").filter(function(i,t){var r=e(t).attr("name");return!h[r]&&(h[r]=!0,!0)}).length+1}var b=m+"-"+d[m];w=b+s.match(/-\d+$/)[0],a.find("label[for="+v+"]").attr("for",b)}else u=new RegExp("-\\d+$"),m=s.replace(u,""),d[m]||(d[m]=t.find(".siteorigin-widget-input[id^="+m+"]").not("[id*=_id_]").length+1),w=m+"-"+d[m]++;i.attr("id",w),a.find("label[for="+s+"]").attr("for",w),a.find("[id*="+s+"]").each(function(){var i=e(this).attr("id"),t=i.replace(s,w);e(this).attr("id",t)}),"undefined"!=typeof tinymce&&tinymce.get(w)&&tinymce.get(w).remove()}var y=n.parents(".siteorigin-widget-field-repeater").length,F=e("body");(F.hasClass("wp-customizer")||F.hasClass("widgets-php"))&&0===r.closest(".panel-dialog").length&&(y+=1);var k=l.replace(new RegExp("((?:.*?\\[\\d+\\]){"+(y-1).toString()+"})?(.*?\\[)\\d+(\\])"),"$1$2"+o.toString()+"$3");i.attr("name",k),i.data("original-name",k)}),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],a=n.split("]["),s=a.length?r:null;a.length;)s=s[a.shift()];return s[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.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;r=r[1];var n=r.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("SELECT"===i.prop("tagName")){var d=i.find("option:selected");1===d.length?s=i.find("option:selected").val():d.length>1&&(s=_.map(i.find("option:selected"),function(i,t){return e(i).val()}))}else s=i.val();for(var l=0;l<n.length;l++)l===n.length-1?""===n[l]?a.push(s):a[n[l]]=s:(_.isUndefined(a[n[l]])&&(_.isNumber(n[l+1])||""===n[l+1]?a[n[l]]=[]:a[n[l]]={}),a=a[n[l]])}catch(e){console.error("Field ["+i.attr("name")+"] could not be processed and was skipped - "+e.message)}}),t},sowbForms.setWidgetFormValues=function(i,t,r){r=r||!1;var n=0,a=function(i,t){10!=++n&&i.find("> .siteorigin-widget-field-type-repeater").each(function(){var i=e(this).find("> .siteorigin-widget-field-repeater"),n=i.data("repeaterName"),s=t.hasOwnProperty(n)?t[n]:null;if(s&&Array.isArray(s)){var o=i.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item"),d=s.length,l=o.length;if(d>l)for(var g=0;g<d-l;g++)i.find("> .siteorigin-widget-field-repeater-add").click();else if(!r&&d<l)for(var f=d;f<l;f++){var c=e(o.eq(f));c.find("> .siteorigin-widget-field-repeater-item-top").find(".siteorigin-widget-field-remove").trigger("click",{silent:!0})}o=i.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item");for(var p=0;p<o.length;p++)o.eq(p).find("> .siteorigin-widget-field-repeater-item-form"),a(o.eq(p).find("> .siteorigin-widget-field-repeater-item-form"),s[p])}})};a(i,t),i.find("*[name]").each(function(){var i=e(this),n=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(void 0===n||null===n)return!0;n=n[1];var a=n.split("][");a=a.map(function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e});for(var s,o=t,d=0;d<a.length;d++){if(!o.hasOwnProperty(a[d])){if(r)return!0;break}d===a.length-1?s=o[a[d]]:o=o[a[d]]}if("checkbox"===i.attr("type"))i.prop("checked",s);else if("radio"===i.attr("type"))i.prop("checked",s===i.val());else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var l=null;"undefined"!=typeof tinyMCE&&(l=tinyMCE.get(i.attr("id"))),null===l||"function"!=typeof l.getContent||l.isHidden()?i.val(s):l.setContent(s)}else i.val(s);i.trigger("change")})},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)}),e("body").hasClass("wp-customizer")&&e(document).on("widget-added",function(e,i){i.find(".siteorigin-widget-form").sowSetupForm()}),e(document).on("open_dialog",function(i,t){if(t.$el.find(".so-panels-dialog").is(".so-panels-dialog-edit-widget")){e(i.target).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+") *$"),r=t.exec(e);if(null===r)return!1;var n="",a="default";return void 0!==r[3]?(a=r[1],n=r[3]):n=r[1],{match:r[4].trim(),group:a,state:n}},_checker:function(e,i,t,r){var n={};void 0===i.length&&(i=[i]);for(var a,s=0;s<i.length;s++)!1!==(a=sowEmitters._match(i[s],t))&&("_true"===a.match||r(e,i,a.match))&&(n[a.group]=a.state);return n},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=e(this),n=e.extend({},i.data("state-handler"),a?i.data("state-handler-initial"):{});if(0===Object.keys(n).length)return!0;var s,o,d,l,g,f,c={},p=sowbForms.getContainerFieldId(i,"repeater",".siteorigin-widget-field-repeater-item");if(!1!==p){var u={};for(var m in n)u[m.replace("{$repeater}",p)]=n[m];n=u}var w=sowbForms.getContainerFieldId(i,"widget",".siteorigin-widget-widget");if(!1!==w){var v={};for(var h in n){var b=h.match(/_else\[(.*)\]|(.*)\[(.*)\]/),y="";y=b&&b.length&&void 0===b[1]?b[2]+"_"+w+"["+b[3]+"]":"_else["+b[1]+"_"+w+"]",v[y]=n[h]}n=v}for(var F in n)if(g=!1,null!==(s=F.match(/^([a-zA-Z0-9_-]+)(\[([a-zA-Z0-9_\-,]+)\])?(\[\])?$/))){if(o={group:"default",name:"",multi:!1},void 0!==s[2]?(o.group=s[1],o.name=s[3]):o.name=s[0],o.multi=void 0!==s[4],"_else"===o.group)o.group=o.name,o.name="",g=o.group===t&&void 0===c[o.group];else{f=o.name.split(",").map(function(e){return e.trim()});for(var k=0;k<f.length&&!(g=o.group===t&&f[k]===r);k++);}if(g){d=n[F],o.multi||(d=[d]);for(var k=0;k<d.length;k++)l=void 0!==d[k][1]&&Boolean(d[k][1])?i.find(d[k][1]):i,l[d[k][0]].apply(l,void 0!==d[k][2]?d[k][2]:[]);c[o.group]=!0}}})}),n.sowSetupPreview(),r=n;var d=n.find(".siteorigin-widget-teaser");d.find(".dashicons-dismiss").click(function(){var i=e(this);e.get(i.data("dismiss-url")),d.slideUp("normal",function(){d.remove()})});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));if(c)if(c._sow_form_timestamp>f){var p=e('<div class="siteorigin-widget-form-notification"><span>'+soWidgets.backup.newerVersion+'</span><a class="button button-small so-backup-restore">'+soWidgets.backup.restore+'</a><a class="button button-small so-backup-dismiss">'+soWidgets.backup.dismiss+"</a><div><small>"+soWidgets.backup.replaceWarning+"</small></div></div>");n.prepend(p),p.find(".so-backup-restore").click(function(){sowbForms.setWidgetFormValues(r,c),p.slideUp("fast",function(){p.remove()})}),p.find(".so-backup-dismiss").click(function(){p.slideUp("fast",function(){sessionStorage.removeItem(l),p.remove()})})}else 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 u=n.find("> .siteorigin-widget-field");u.find("> .siteorigin-widget-section").sowSetupForm();var m=u.find("> .siteorigin-widget-widget");m.find("> .siteorigin-widget-section").sowSetupForm(),m.filter(":not(:has(> .siteorigin-widget-section))").sowSetupForm(),u.find(".siteorigin-widget-input").each(function(i,t){null===e(t).data("original-name")&&e(t).data("original-name",e(t).attr("name"))}),u.find("> .siteorigin-widget-field-repeater").sowSetupRepeater(),n.find(".siteorigin-widget-field-repeater-item").sowSetupRepeaterItems(),u.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(){if(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")}})};u.filter(".siteorigin-widget-field-type-widget, .siteorigin-widget-field-type-section").find("> label").click(w),u.filter(".siteorigin-widget-field-type-posts").find(".posts-container-label-wrapper").click(w),u.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,i){t.val(parseFloat(i.value)),t.trigger("change")},change:function(e,t){i.find(".siteorigin-widget-slider-value").html(t.value)}}),t.change(function(e,i){i&&i.silent||r.slider("value",parseFloat(t.val()))})}),u.filter(".siteorigin-widget-field-type-link").each(function(){var i=e(this),t=null,r=function(){null!==t&&t.abort();var r=i.find(".content-text-search"),n=r.val(),a=r.data("postTypes"),s=i.find("ul.posts").empty().addClass("loading");e.get(soWidgets.ajaxurl,{action:"so_widgets_search_posts",query:n,postTypes:a},function(i){for(var t=0;t<i.length;t++)""===i[t].label&&(i[t].label="&nbsp;"),s.append(e("<li>").addClass("post").html(i[t].label+"<span>("+i[t].type+")</span>").data(i[t]));s.removeClass("loading")})};i.find(".select-content-button, .button-close").click(function(t){t.preventDefault(),e(this).blur();var n=i.find(".existing-content-selector");n.toggle(),n.is(":visible")&&0===n.find("ul.posts li").length&&r()}),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.find(".existing-content-selector").toggle()});var n=null;i.find(".content-text-search").keyup(function(){null!==n&&clearTimeout(n),n=setTimeout(function(){r()},500)})}),void 0!==jQuery.fn.soPanelsSetupBuilderWidget&&u.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 v=function(){var i=e(this),t=i.closest("[data-state-emitter]").data("state-emitter");if(void 0!==t){var n={default:""};void 0===t.length&&(t=[t]);for(var a=0;a<t.length;a++)n=function(t,r){if(void 0===sowEmitters[t.callback]||"_"===t.callback.substr(0,1))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+"_"+a}));var s=i.is('[type="checkbox"]')?i.is(":checked"):i.val();return e.extend(r,sowEmitters[t.callback](s,t.args))}(t[a],n);var s=r.data("states");void 0===s&&(s={default:""});for(var o in n)void 0!==s[o]&&n[o]===s[o]||(s[o]=n[o],r.trigger("sowstatechange",[o,n[o]]));r.data("states",s)}};u.filter("[data-state-emitter]").each(function(){var i=e(this).find(".siteorigin-widget-input");i.on("keyup change",v),i.each(function(){var i=e(this);i.is(":radio")?i.is(":checked")&&v.call(i[0]):v.call(i[0])})}),n.trigger("sowsetupform",u).data("sow-form-setup",!0),u.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){if(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")});else{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.html().replace(/_id_/g,n),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(){if(e(window).resize(),e(this).is(":visible")){e(this).trigger("slideToggleOpenComplete");e(this).find("> .siteorigin-widget-field").trigger("sowsetupformfield")}else e(this).trigger("slideToggleCloseComplete")}))}),a.find(".siteorigin-widget-field-remove").click(function(i,t){i.preventDefault();var n=e(this).closest(".siteorigin-widget-field-repeater-items"),a=e(this).closest(".siteorigin-widget-field-repeater-item"),s=function(){a.remove(),n.sortable("refresh").trigger("updateFieldPositions"),e(window).resize()};t&&t.silent?s():confirm(soWidgets.sure)&&a.slideUp("fast",s),r.trigger("change")}),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,m,w;if(i.is('[type="radio"]')){m=s.replace(/-\d+-\d+$/,"");var v=s.replace(/-\d+$/,"");if(!d[m]){var h={};d[m]=t.find(".siteorigin-widget-input[id^="+m+"]").not("[id*=_id_]").filter(function(i,t){var r=e(t).attr("name");return!h[r]&&(h[r]=!0,!0)}).length+1}var b=m+"-"+d[m];w=b+s.match(/-\d+$/)[0],a.find("label[for="+v+"]").attr("for",b)}else u=new RegExp("-\\d+$"),m=s.replace(u,""),d[m]||(d[m]=t.find(".siteorigin-widget-input[id^="+m+"]").not("[id*=_id_]").length+1),w=m+"-"+d[m]++;i.attr("id",w),a.find("label[for="+s+"]").attr("for",w),a.find("[id*="+s+"]").each(function(){var i=e(this).attr("id"),t=i.replace(s,w);e(this).attr("id",t)}),"undefined"!=typeof tinymce&&tinymce.get(w)&&tinymce.get(w).remove()}var y=n.parents(".siteorigin-widget-field-repeater").length,F=e("body");(F.hasClass("wp-customizer")||F.hasClass("widgets-php"))&&0===r.closest(".panel-dialog").length&&(y+=1);var k=l.replace(new RegExp("((?:.*?\\[\\d+\\]){"+(y-1).toString()+"})?(.*?\\[)\\d+(\\])"),"$1$2"+o.toString()+"$3");i.attr("name",k),i.data("original-name",k)}),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],a=n.split("]["),s=a.length?r:null;a.length;)s=s[a.shift()];return s[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.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;r=r[1];var n=r.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("SELECT"===i.prop("tagName")){var d=i.find("option:selected");1===d.length?s=i.find("option:selected").val():d.length>1&&(s=_.map(i.find("option:selected"),function(i,t){return e(i).val()}))}else s=i.val();for(var l=0;l<n.length;l++)l===n.length-1?""===n[l]?a.push(s):a[n[l]]=s:(_.isUndefined(a[n[l]])&&(_.isNumber(n[l+1])||""===n[l+1]?a[n[l]]=[]:a[n[l]]={}),a=a[n[l]])}catch(e){console.error("Field ["+i.attr("name")+"] could not be processed and was skipped - "+e.message)}}),t},sowbForms.setWidgetFormValues=function(i,t,r){r=r||!1;var n=0,a=function(i,t){10!=++n&&i.find("> .siteorigin-widget-field-type-repeater").each(function(){var i=e(this).find("> .siteorigin-widget-field-repeater"),n=i.data("repeaterName"),s=t.hasOwnProperty(n)?t[n]:null;if(s&&Array.isArray(s)){var o=i.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item"),d=s.length,l=o.length;if(d>l)for(var g=0;g<d-l;g++)i.find("> .siteorigin-widget-field-repeater-add").click();else if(!r&&d<l)for(var f=d;f<l;f++){var c=e(o.eq(f));c.find("> .siteorigin-widget-field-repeater-item-top").find(".siteorigin-widget-field-remove").trigger("click",{silent:!0})}o=i.find("> .siteorigin-widget-field-repeater-items > .siteorigin-widget-field-repeater-item");for(var p=0;p<o.length;p++)o.eq(p).find("> .siteorigin-widget-field-repeater-item-form"),a(o.eq(p).find("> .siteorigin-widget-field-repeater-item-form"),s[p])}})};a(i,t),i.find("*[name]").each(function(){var i=e(this),n=/[a-zA-Z0-9\-]+\[[a-zA-Z0-9]+\]\[(.*)\]/.exec(i.attr("name"));if(void 0===n||null===n)return!0;n=n[1];var a=n.split("][");a=a.map(function(e){return!isNaN(parseFloat(e))&&isFinite(e)?parseInt(e):e});for(var s,o=t,d=0;d<a.length;d++){if(!o.hasOwnProperty(a[d])){if(r)return!0;break}d===a.length-1?s=o[a[d]]:o=o[a[d]]}if("checkbox"===i.attr("type"))i.prop("checked",s);else if("radio"===i.attr("type"))i.prop("checked",s===i.val());else if("TEXTAREA"===i.prop("tagName")&&i.hasClass("wp-editor-area")){var l=null;"undefined"!=typeof tinyMCE&&(l=tinyMCE.get(i.attr("id"))),null===l||"function"!=typeof l.getContent||l.isHidden()?i.val(s):l.setContent(s)}else i.val(s);i.trigger("change")})},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)}),e("body").hasClass("wp-customizer")&&e(document).on("widget-added",function(e,i){i.find(".siteorigin-widget-form").sowSetupForm()}),e(document).on("open_dialog",function(i,t){if(t.$el.find(".so-panels-dialog").is(".so-panels-dialog-edit-widget")){e(i.target).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+") *$"),r=t.exec(e);if(null===r)return!1;var n="",a="default";return void 0!==r[3]?(a=r[1],n=r[3]):n=r[1],{match:r[4].trim(),group:a,state:n}},_checker:function(e,i,t,r){var n={};void 0===i.length&&(i=[i]);for(var a,s=0;s<i.length;s++)!1!==(a=sowEmitters._match(i[s],t))&&("_true"===a.match||r(e,i,a.match))&&(n[a.group]=a.state);return n},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;
base/siteorigin-widget.class.php CHANGED
@@ -1,1361 +1,1363 @@
1
- <?php
2
-
3
- /**
4
- * Class SiteOrigin_Widget
5
- *
6
- * @author SiteOrigin <support@siteorigin.com>
7
- */
8
- abstract class SiteOrigin_Widget extends WP_Widget {
9
- protected $form_options;
10
- protected $base_folder;
11
- protected $field_ids;
12
- protected $fields;
13
-
14
- /**
15
- * The name of this widget class. Whatever the key for $wp_widgets_factory is.
16
- *
17
- * @var string
18
- */
19
- protected $widget_class;
20
-
21
- /**
22
- * @var array The array of registered frontend scripts
23
- */
24
- protected $frontend_scripts = array();
25
-
26
- /**
27
- * @var array The array of registered frontend styles
28
- */
29
- protected $frontend_styles = array();
30
-
31
- protected $generated_css = array();
32
- protected $current_instance;
33
- protected $instance_storage;
34
-
35
- /**
36
- * @var int How many seconds a CSS file is valid for.
37
- */
38
- static $css_expire = 604800; // 7 days
39
-
40
- /**
41
- * @param string $id
42
- * @param string $name
43
- * @param array $widget_options Optional Normal WP_Widget widget options and a few extras.
44
- * - help: A URL which, if present, causes a help link to be displayed on the Edit Widget modal.
45
- * - instance_storage: Whether or not to temporarily store instances of this widget.
46
- * - has_preview: Whether or not this widget has a preview to display. If false, the form does not output a
47
- * 'Preview' button.
48
- * @param array $control_options Optional Normal WP_Widget control options.
49
- * @param array $form_options Optional An array describing the form fields used to configure SiteOrigin widgets.
50
- * @param mixed $base_folder Optional
51
- *
52
- */
53
- function __construct($id, $name, $widget_options = array(), $control_options = array(), $form_options = array(), $base_folder = false) {
54
- $this->form_options = $form_options;
55
- $this->base_folder = $base_folder;
56
- $this->field_ids = array();
57
- $this->fields = array();
58
-
59
- $widget_options = wp_parse_args( $widget_options, array(
60
- 'has_preview' => true,
61
- ) );
62
-
63
- $control_options = wp_parse_args( $control_options, array(
64
- 'width' => 800,
65
- ) );
66
-
67
- if( empty( $this->widget_class ) ) {
68
- $this->widget_class = get_class( $this );
69
- }
70
-
71
- parent::__construct($id, $name, $widget_options, $control_options);
72
- $this->initialize();
73
-
74
- // Let other plugins do additional initializing here
75
- do_action('siteorigin_widgets_initialize_widget_' . $this->id_base, $this);
76
- }
77
-
78
- /**
79
- * Initialize this widget in whatever way we need to. Run before rendering widget or form.
80
- */
81
- function initialize(){
82
-
83
- }
84
-
85
- /**
86
- * Get the main widget form. This should be overwritten by child widgets.
87
- *
88
- * @return array
89
- */
90
- function get_widget_form(){
91
- return method_exists( $this, 'initialize_form' ) ? $this->initialize_form() : array();
92
- }
93
-
94
- private function get_cached_widget_form() {
95
- $cache_key = $this->id_base . '_form';
96
- $form_options = wp_cache_get( $cache_key, 'siteorigin_widgets' );
97
-
98
- if ( empty( $form_options ) ) {
99
- $form_options = $this->get_widget_form();
100
- wp_cache_set( $cache_key, $form_options, 'siteorigin_widgets' );
101
- }
102
-
103
- return $form_options;
104
- }
105
-
106
- /**
107
- * Check if a child widget implements a specific form type.
108
- *
109
- * @param string $form_type
110
- * @return bool
111
- */
112
- function has_form( $form_type = 'widget' ){
113
- return method_exists( $this, 'get_' . $form_type . '_form' );
114
- }
115
-
116
- /**
117
- * Get a specific type of form.
118
- *
119
- * @param $form_type
120
- * @return array The form array, or an empty array if the form doesn't exist.
121
- */
122
- function get_form( $form_type ) {
123
- return $this->has_form( $form_type ) ? call_user_func( array( $this, 'get_' . $form_type . '_form' ) ) : array();
124
- }
125
-
126
- /**
127
- * Get the main form options and allow child widgets to modify that form.
128
- *
129
- * @param bool|SiteOrigin_Widget $parent
130
- *
131
- * @return mixed
132
- */
133
- function form_options( $parent = false ) {
134
- if( empty( $this->form_options ) ) {
135
- // If the widget doesn't have form_options defined from the constructor, then it might be defining them in the get_widget_form function
136
- $this->form_options = $this->get_cached_widget_form();
137
- }
138
-
139
- $form_options = $this->modify_form( $this->form_options );
140
- if( !empty($parent) ) {
141
- $form_options = $parent->modify_child_widget_form( $form_options, $this );
142
- }
143
-
144
- // Give other plugins a way to modify this form.
145
- $form_options = apply_filters( 'siteorigin_widgets_form_options', $form_options, $this );
146
- $form_options = apply_filters( 'siteorigin_widgets_form_options_' . $this->id_base, $form_options, $this );
147
- return $form_options;
148
- }
149
-
150
- /**
151
- * Display the widget.
152
- *
153
- * @param array $args
154
- * @param array $instance
155
- */
156
- public function widget( $args, $instance ) {
157
- if( empty( $this->form_options ) ) {
158
- $form_options = $this->get_cached_widget_form();
159
- }
160
- else {
161
- $form_options = $this->modify_form( $this->form_options );
162
- }
163
-
164
- $instance = $this->modify_instance( $instance );
165
-
166
- // Filter the instance
167
- $instance = apply_filters( 'siteorigin_widgets_instance', $instance, $this );
168
- $instance = apply_filters( 'siteorigin_widgets_instance_' . $this->id_base, $instance, $this );
169
-
170
- $args = wp_parse_args( $args, array(
171
- 'before_widget' => '',
172
- 'after_widget' => '',
173
- 'before_title' => '',
174
- 'after_title' => '',
175
- ) );
176
-
177
- // Add any missing default values to the instance
178
- $instance = $this->add_defaults( $form_options, $instance );
179
-
180
- $css_name = $this->generate_and_enqueue_instance_styles( $instance );
181
- $this->enqueue_frontend_scripts( $instance );
182
-
183
- $template_vars = $this->get_template_variables($instance, $args);
184
- $template_vars = apply_filters( 'siteorigin_widgets_template_variables_' . $this->id_base, $template_vars, $instance, $args, $this );
185
-
186
- // Storage hash allows templates to get access to
187
- $template_vars[ 'storage_hash' ] = '';
188
- if( !empty($this->widget_options['instance_storage']) ) {
189
- $stored_instance = $this->modify_stored_instance($instance);
190
- // We probably don't want panels_info
191
- unset( $stored_instance['panels_info'] );
192
-
193
- $template_vars[ 'storage_hash' ] = substr( md5( serialize( $stored_instance ) ), 0, 8 );
194
- if( !empty( $stored_instance ) && !$this->is_preview( $instance ) ) {
195
- // Store this if we have a non empty instance and are not previewing
196
- set_transient('sow_inst[' . $this->id_base . '][' . $template_vars['storage_hash'] . ']', $stored_instance, 7*86400);
197
- }
198
- }
199
-
200
- if( ! method_exists( $this, 'get_html_content' ) ) {
201
- $template_file = siteorigin_widget_get_plugin_dir_path( $this->id_base ) . $this->get_template_dir( $instance ) . '/' . $this->get_template_name( $instance ) . '.php';
202
- $template_file = apply_filters('siteorigin_widgets_template_file_' . $this->id_base, $template_file, $instance, $this );
203
- $template_file = realpath($template_file);
204
-
205
- // Don't accept non PHP files
206
- if( substr($template_file, -4) != '.php' ) $template_file = false;
207
-
208
- ob_start();
209
- if( !empty($template_file) && file_exists($template_file) ) {
210
- extract( $template_vars );
211
- @ include $template_file;
212
- }
213
- $template_html = ob_get_clean();
214
-
215
- // This is a legacy, undocumented filter.
216
- $template_html = apply_filters( 'siteorigin_widgets_template', $template_html, $this->widget_class, $instance, $this );
217
- $template_html = apply_filters( 'siteorigin_widgets_template_html_' . $this->id_base, $template_html, $instance, $this );
218
- }
219
- else {
220
- $template_html = $this->get_html_content( $instance, $args, $template_vars, $css_name );
221
- }
222
-
223
- $wrapper_classes = apply_filters(
224
- 'siteorigin_widgets_wrapper_classes_' . $this->id_base,
225
- array( 'so-widget-' . $this->id_base, 'so-widget-'.$css_name ),
226
- $instance,
227
- $this
228
- );
229
- $wrapper_classes = array_map( 'sanitize_html_class', $wrapper_classes );
230
-
231
- $wrapper_data_string = $this->get_wrapper_data( $instance );
232
-
233
- do_action( 'siteorigin_widgets_before_widget_' . $this->id_base, $instance, $this );
234
- echo $args['before_widget'];
235
- echo '<div class="' . esc_attr( implode( ' ', $wrapper_classes ) ) . '"' . $wrapper_data_string . '>';
236
- echo $template_html;
237
- echo '</div>';
238
- echo $args['after_widget'];
239
- do_action( 'siteorigin_widgets_after_widget_' . $this->id_base, $instance, $this );
240
- }
241
-
242
- private function get_wrapper_data( $instance ) {
243
- $data = apply_filters(
244
- 'siteorigin_widgets_wrapper_data_' . $this->id_base,
245
- array(),
246
- $instance,
247
- $this
248
- );
249
- $wrapper_attr_string = '';
250
- foreach ( $data as $name => $value ) {
251
- $wrapper_attr_string .= ' data-' . esc_html( $name ) . '="' . esc_attr( $value ) . '"';
252
- }
253
-
254
- return $wrapper_attr_string;
255
- }
256
-
257
- /**
258
- * Generate the CSS for this widget and display it in the appropriate way
259
- *
260
- * @param $instance array The instance array
261
- *
262
- * @return string The CSS name
263
- */
264
- function generate_and_enqueue_instance_styles( $instance ) {
265
- if( empty( $form_options ) ) {
266
- $form_options = $this->get_cached_widget_form();
267
- }
268
- else {
269
- $form_options = $this->modify_form( $this->form_options );
270
- }
271
-
272
- // We'll assume empty instances don't have styles
273
- if( empty($instance) ) return;
274
-
275
- // Make sure all the default values are in place
276
- $instance = $this->add_defaults( $form_options, $instance );
277
-
278
- $this->current_instance = $instance;
279
- $style = $this->get_style_name( $instance );
280
-
281
- $upload_dir = wp_upload_dir();
282
- $this->clear_file_cache();
283
-
284
- if( !empty($style) ) {
285
- $hash = $this->get_style_hash( $instance );
286
- $css_name = $this->id_base.'-'.$style.'-'.$hash;
287
-
288
- //Ensure styles aren't generated and enqueued more than once.
289
- $in_preview = $this->is_preview( $instance );
290
- if ( ! in_array( $css_name, $this->generated_css ) || $in_preview ) {
291
- if( $in_preview ) {
292
- siteorigin_widget_add_inline_css( $this->get_instance_css( $instance ) );
293
- }
294
- else {
295
- if( !file_exists( $upload_dir['basedir'] . '/siteorigin-widgets/' . $css_name .'.css' ) || ( defined('SITEORIGIN_WIDGETS_DEBUG') && SITEORIGIN_WIDGETS_DEBUG ) ) {
296
- // Attempt to recreate the CSS
297
- $this->save_css( $instance );
298
- }
299
-
300
- if( file_exists( $upload_dir['basedir'] . '/siteorigin-widgets/' . $css_name .'.css' ) ) {
301
- if ( ! wp_style_is( $css_name ) ) {
302
- wp_enqueue_style(
303
- $css_name,
304
- set_url_scheme($upload_dir['baseurl'] . '/siteorigin-widgets/' . $css_name .'.css')
305
- );
306
- }
307
- }
308
- else {
309
- // Fall back to using inline CSS if we can't find the cached CSS file.
310
- // Try get the cached value.
311
- $css = wp_cache_get( $css_name, 'siteorigin_widgets' );
312
- if ( empty( $css ) ) {
313
- $css = $this->get_instance_css( $instance );
314
- }
315
- siteorigin_widget_add_inline_css( $css );
316
- }
317
- }
318
- $this->generated_css[] = $css_name;
319
- }
320
- }
321
- else {
322
- $css_name = $this->id_base.'-base';
323
- }
324
-
325
- $this->current_instance = false;
326
- return $css_name;
327
- }
328
-
329
- private function is_customize_preview(){
330
- global $wp_customize;
331
- return is_a( $wp_customize, 'WP_Customize_Manager' ) && $wp_customize->is_preview();
332
- }
333
-
334
- /**
335
- * Get an array of variables to make available to templates. By default, just return an array. Should be overwritten by child widgets.
336
- *
337
- * @param $instance
338
- * @param $args
339
- *
340
- * @return array
341
- */
342
- public function get_template_variables( $instance, $args ){
343
- return array();
344
- }
345
-
346
- /**
347
- * Render a sub widget. This should be used inside template files.
348
- *
349
- * @param $class
350
- * @param $args
351
- * @param $instance
352
- */
353
- public function sub_widget($class, $args, $instance){
354
- if(!class_exists($class)) return;
355
- $widget = new $class;
356
-
357
- $args['before_widget'] = '';
358
- $args['after_widget'] = '';
359
-
360
- $widget->widget( $args, $instance );
361
- }
362
-
363
- /**
364
- * Add default values to the instance.
365
- *
366
- * @param $form
367
- * @param $instance
368
- */
369
- function add_defaults( $form, $instance, $level = 0 ){
370
- if( $level > 10 ) return $instance;
371
-
372
- foreach($form as $id => $field) {
373
-
374
- if( $field['type'] == 'repeater' ) {
375
- if( !empty($instance[$id]) ) {
376
- foreach( array_keys($instance[$id]) as $i ){
377
- $instance[$id][$i] = $this->add_defaults( $field['fields'], $instance[$id][$i], $level + 1 );
378
- }
379
- }
380
- }
381
- else if( $field['type'] == 'section' ) {
382
- if( empty($instance[$id]) ) {
383
- $instance[$id] = array();
384
- }
385
- $instance[$id] = $this->add_defaults( $field['fields'], $instance[$id], $level + 1 );
386
- }
387
- else if( $field['type'] == 'measurement' ) {
388
- if( ! isset( $instance[$id] ) ) {
389
- $instance[$id] = isset( $field['default'] ) ? $field['default'] : '';
390
- }
391
- if ( empty( $instance[ $id . '_unit' ] ) ) {
392
- $instance[ $id . '_unit' ] = 'px';
393
- }
394
- }
395
- else if ( $field['type'] == 'order') {
396
- if ( empty( $instance[$id] ) ) {
397
- if( ! empty( $field['default'] ) ) {
398
- $instance[$id] = $field['default'];
399
- } else {
400
- // If no default order is specified, just use the order of the options.
401
- $instance[$id] = array_keys( $field['options'] );
402
- }
403
- }
404
- }
405
- else {
406
- if( !isset( $instance[$id] ) ) {
407
- $instance[$id] = isset( $field['default'] ) ? $field['default'] : '';
408
- }
409
- }
410
- }
411
-
412
- return $instance;
413
- }
414
-
415
- /**
416
- * Display the widget form.
417
- *
418
- * @param array $instance
419
- * @param string $form_type Which type of form we're using
420
- *
421
- * @return string|void
422
- */
423
- public function form( $instance, $form_type = 'widget' ) {
424
- if( $form_type == 'widget' ) {
425
- if( empty( $this->form_options ) ) {
426
- $this->form_options = $this->form_options();
427
- }
428
- $form_options = $this->form_options;
429
- }
430
- else {
431
- $form_options = $this->get_form( $form_type );
432
- }
433
-
434
- $instance = $this->modify_instance($instance);
435
- $instance = $this->add_defaults( $form_options, $instance );
436
-
437
- if( empty( $this->number ) ) {
438
- // Compatibility with form widgets.
439
- $this->number = 1;
440
- }
441
-
442
- // Filter the instance specifically for the form
443
- $instance = apply_filters('siteorigin_widgets_form_instance_' . $this->id_base, $instance, $this);
444
-
445
- $form_id = 'siteorigin_widget_form_'.md5( uniqid( rand(), true ) );
446
- $class_name = str_replace( '_', '-', strtolower( $this->widget_class ) );
447
-
448
- if( empty( $instance['_sow_form_id'] ) ) {
449
- $instance['_sow_form_id'] = uniqid();
450
- }
451
- ?>
452
- <div class="siteorigin-widget-form siteorigin-widget-form-main siteorigin-widget-form-main-<?php echo esc_attr($class_name) ?>" id="<?php echo $form_id ?>" data-class="<?php echo esc_attr( $this->widget_class ) ?>" style="display: none">
453
- <?php
454
- $this->display_teaser_message();
455
- /* @var $field_factory SiteOrigin_Widget_Field_Factory */
456
- $field_factory = SiteOrigin_Widget_Field_Factory::single();
457
- $fields_javascript_variables = array();
458
- foreach( $form_options as $field_name => $field_options ) {
459
- /* @var $field SiteOrigin_Widget_Field_Base */
460
- $field = $field_factory->create_field( $field_name, $field_options, $this );
461
- $field->render( isset( $instance[$field_name] ) ? $instance[$field_name] : null, $instance );
462
- $field_js_vars = $field->get_javascript_variables();
463
- if( ! empty( $field_js_vars ) ) {
464
- $fields_javascript_variables[$field_name] = $field_js_vars;
465
- }
466
- $field->enqueue_scripts();
467
- $this->fields[$field_name] = $field;
468
- }
469
- ?>
470
- <input type="hidden" name="<?php echo $this->so_get_field_name('_sow_form_id') ?>" value="<?php echo esc_attr( $instance['_sow_form_id'] ) ?>" class="siteorigin-widgets-form-id" />
471
- <input type="hidden" name="<?php echo $this->so_get_field_name('_sow_form_timestamp') ?>" value="<?php echo ! empty( $instance['_sow_form_timestamp'] ) ? esc_attr( $instance['_sow_form_timestamp'] ) : '' ?>" class="siteorigin-widgets-form-timestamp" />
472
- </div>
473
- <div class="siteorigin-widget-form-no-styles">
474
- <?php $this->scripts_loading_message() ?>
475
- </div>
476
-
477
- <?php if( $this->show_preview_button() ) : ?>
478
- <div class="siteorigin-widget-preview" style="display: none">
479
- <a href="#" class="siteorigin-widget-preview-button button-secondary"><?php _e('Preview', 'so-widgets-bundle') ?></a>
480
- </div>
481
- <?php endif; ?>
482
-
483
- <?php if( !empty( $this->widget_options['help'] ) ) : ?>
484
- <a href="<?php echo sow_esc_url($this->widget_options['help']) ?>" class="siteorigin-widget-help-link siteorigin-panels-help-link" target="_blank" rel="noopener noreferrer"><?php _e('Help', 'so-widgets-bundle') ?></a>
485
- <?php endif; ?>
486
-
487
- <script type="text/javascript">
488
- ( function($) {
489
- if(typeof window.sow_field_javascript_variables == 'undefined') window.sow_field_javascript_variables = {};
490
- window.sow_field_javascript_variables["<?php echo addslashes( $this->widget_class ) ?>"] = <?php echo json_encode( $fields_javascript_variables ) ?>;
491
-
492
- if( typeof $.fn.sowSetupForm != 'undefined' ) {
493
- $('#<?php echo $form_id ?>').sowSetupForm();
494
- }
495
- else {
496
- // Init once admin scripts have been loaded
497
- $( document).on('sowadminloaded', function(){
498
- $('#<?php echo $form_id ?>').sowSetupForm();
499
- });
500
- }
501
- } )( jQuery );
502
- </script>
503
- <?php
504
-
505
- $this->enqueue_scripts( $form_type );
506
- }
507
-
508
- /**
509
- * Display the teaser message.
510
- */
511
- function display_teaser_message(){
512
- if(
513
- method_exists( $this, 'get_form_teaser' ) &&
514
- ( $teaser = $this->get_form_teaser() )
515
- ) {
516
- if ( ! is_admin() ) {
517
- wp_enqueue_style( 'dashicons' );
518
- }
519
-
520
- $dismissed = get_user_meta( get_current_user_id(), 'teasers_dismissed', true );
521
- if( empty( $dismissed[ $this->id_base ] ) ) {
522
- $dismiss_url = add_query_arg( array(
523
- 'action' => 'so_dismiss_widget_teaser',
524
- 'widget' => $this->id_base,
525
- ), admin_url( 'admin-ajax.php' ) );
526
- $dismiss_url = wp_nonce_url( $dismiss_url, 'dismiss-widget-teaser' );
527
-
528
- ?>
529
- <div class="siteorigin-widget-teaser">
530
- <?php echo wp_kses_post( $teaser ) ?>
531
- <span class="dashicons dashicons-dismiss" data-dismiss-url="<?php echo esc_url( $dismiss_url ) ?>"></span>
532
- </div>
533
- <?php
534
- }
535
- }
536
- }
537
-
538
- /**
539
- * Should we display the teaser for SiteOrigin Premium
540
- *
541
- * @return bool
542
- */
543
- function display_siteorigin_premium_teaser(){
544
- return apply_filters( 'siteorigin_premium_upgrade_teaser', true ) &&
545
- ! defined( 'SITEORIGIN_PREMIUM_VERSION' );
546
- }
547
-
548
- function scripts_loading_message(){
549
- ?>
550
- <p><strong><?php _e('This widget has scripts and styles that need to be loaded before you can use it. Please save and reload your current page.', 'so-widgets-bundle') ?></strong></p>
551
- <p><strong><?php _e('You will only need to do this once.', 'so-widgets-bundle') ?></strong></p>
552
- <?php
553
- }
554
-
555
- /**
556
- * Enqueue the admin scripts for the widget form.
557
- *
558
- * @param bool|string $form_type Should we enqueue the field scripts too?
559
- */
560
- function enqueue_scripts( $form_type = false ) {
561
-
562
- if( ! wp_script_is('siteorigin-widget-admin') ) {
563
- wp_enqueue_style( 'wp-color-picker' );
564
- wp_enqueue_style( 'siteorigin-widget-admin', plugin_dir_url(SOW_BUNDLE_BASE_FILE).'base/css/admin.css', array( 'media-views' ), SOW_BUNDLE_VERSION );
565
-
566
- wp_enqueue_script( 'wp-color-picker' );
567
- wp_enqueue_media();
568
- wp_enqueue_script(
569
- 'siteorigin-widget-admin',
570
- plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'base/js/admin' . SOW_BUNDLE_JS_SUFFIX . '.js',
571
- array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-slider', 'underscore' ),
572
- SOW_BUNDLE_VERSION,
573
- true
574
- );
575
-
576
- wp_localize_script( 'siteorigin-widget-admin', 'soWidgets', array(
577
- 'ajaxurl' => wp_nonce_url( admin_url('admin-ajax.php'), 'widgets_action', '_widgets_nonce' ),
578
- 'sure' => __('Are you sure?', 'so-widgets-bundle'),
579
- 'backup' => array(
580
- 'newerVersion' => __( "There is a newer version of this widget's content available.", 'so-widgets-bundle' ),
581
- 'restore' => __( 'Restore', 'so-widgets-bundle' ),
582
- 'dismiss' => __( 'Dismiss', 'so-widgets-bundle' ),
583
- 'replaceWarning' => sprintf(
584
- __( 'Clicking %s will replace the current widget contents. You can revert by refreshing the page before updating.', 'so-widgets-bundle' ),
585
- '<em>' . __( 'Restore', 'so-widgets-bundle' ) . '</em>'
586
- ),
587
- ),
588
- ) );
589
-
590
- global $wp_customize;
591
- if ( isset( $wp_customize ) ) {
592
- $this->footer_admin_templates();
593
- }
594
- else {
595
- add_action( 'admin_footer', array( $this, 'footer_admin_templates' ) );
596
- }
597
- }
598
-
599
- if( !empty( $form_type ) && $this->has_form( $form_type ) ) {
600
- // Enqueue field scripts for the given form type
601
- $form_options = $this->get_form( $form_type );
602
- $this->enqueue_field_scripts( $form_options );
603
- }
604
-
605
- // This lets the widget enqueue any specific admin scripts
606
- $this->enqueue_admin_scripts();
607
- do_action( 'siteorigin_widgets_enqueue_admin_scripts_' . $this->id_base, $this );
608
- }
609
-
610
- function enqueue_field_scripts( $fields ){
611
- /* @var $field_factory SiteOrigin_Widget_Field_Factory */
612
- $field_factory = SiteOrigin_Widget_Field_Factory::single();
613
-
614
- foreach( $fields as $field_name => $field_options ) {
615
- /* @var $field SiteOrigin_Widget_Field_Base */
616
- $field = $field_factory->create_field( $field_name, $field_options, $this );
617
- $field->enqueue_scripts();
618
-
619
- if( !empty( $field_options['fields'] ) ) {
620
- $this->enqueue_field_scripts( $field_options['fields'] );
621
- }
622
- }
623
- }
624
-
625
- /**
626
- * Display all the admin stuff for the footer
627
- */
628
- function footer_admin_templates(){
629
- ?>
630
- <script type="text/template" id="so-widgets-bundle-tpl-preview-dialog">
631
- <div class="so-widgets-dialog">
632
- <div class="so-widgets-dialog-overlay"></div>
633
-
634
- <div class="so-widgets-toolbar">
635
- <h3><?php _e( 'Widget Preview', 'so-widgets-bundle' ) ?></h3>
636
- <div class="close"><span class="dashicons dashicons-arrow-left-alt2"></span></div>
637
- </div>
638
-
639
- <div class="so-widgets-dialog-frame">
640
- <iframe name="siteorigin-widgets-preview-iframe" id="siteorigin-widget-preview-iframe" style="visibility: hidden"></iframe>
641
- </div>
642
-
643
- <form target="siteorigin-widgets-preview-iframe" action="<?php echo wp_nonce_url( admin_url('admin-ajax.php'), 'widgets_action', '_widgets_nonce' ) ?>" method="post">
644
- <input type="hidden" name="action" value="so_widgets_preview" />
645
- <input type="hidden" name="data" value="" />
646
- <input type="hidden" name="class" value="" />
647
- </form>
648
-
649
- </div>
650
- </script>
651
- <?php
652
-
653
- // Give other plugins a chance to add their own
654
- do_action('siteorigin_widgets_footer_admin_templates');
655
- }
656
-
657
- /**
658
- * Update the widget instance.
659
- *
660
- * @param array $new_instance
661
- * @param array $old_instance
662
- * @param string $form_type The type of form we're using.
663
- * @return array|void
664
- */
665
- public function update( $new_instance, $old_instance, $form_type = 'widget' ) {
666
- if( !class_exists('SiteOrigin_Widgets_Color_Object') ) require plugin_dir_path( __FILE__ ).'inc/color.php';
667
-
668
- if( $form_type == 'widget' ) {
669
- if( empty( $this->form_options ) ) {
670
- $this->form_options = $this->form_options();
671
- }
672
- $form_options = $this->form_options;
673
- }
674
- else {
675
- $form_options = $this->get_form( $form_type );
676
- }
677
-
678
- if( ! empty( $form_options ) ) {
679
- /* @var $field_factory SiteOrigin_Widget_Field_Factory */
680
- $field_factory = SiteOrigin_Widget_Field_Factory::single();
681
- foreach ( $form_options as $field_name => $field_options ) {
682
- /* @var $field SiteOrigin_Widget_Field_Base */
683
- if ( !empty( $this->fields ) && !empty( $this->fields[$field_name] ) ) {
684
- $field = $this->fields[$field_name];
685
- }
686
- else {
687
- $field = $field_factory->create_field( $field_name, $field_options, $this );
688
- $this->fields[$field_name] = $field;
689
- }
690
- $new_instance[$field_name] = $field->sanitize(
691
- isset( $new_instance[$field_name] ) ? $new_instance[$field_name] : null,
692
- $new_instance,
693
- isset( $old_instance[$field_name] ) ? $old_instance[$field_name] : null
694
- );
695
- $new_instance = $field->sanitize_instance( $new_instance );
696
- }
697
-
698
- // Let other plugins also sanitize the instance
699
- $new_instance = apply_filters( 'siteorigin_widgets_sanitize_instance', $new_instance, $form_options, $this );
700
- $new_instance = apply_filters( 'siteorigin_widgets_sanitize_instance_' . $this->id_base, $new_instance, $form_options, $this );
701
- }
702
-
703
- // Remove the old CSS, it'll be regenerated on page load.
704
- $this->delete_css( $this->modify_instance( $new_instance ) );
705
- return $new_instance;
706
- }
707
-
708
- /**
709
- * Save the CSS to the filesystem
710
- *
711
- * @param $instance
712
- * @return bool|string
713
- */
714
- private function save_css( $instance ){
715
- require_once ABSPATH . 'wp-admin/includes/file.php';
716
-
717
- $style = $this->get_style_name($instance);
718
- $hash = $this->get_style_hash( $instance );
719
- $name = $this->id_base.'-'.$style.'-'.$hash.'.css';
720
-
721
- $css = $this->get_instance_css($instance);
722
-
723
- if( !empty($css) ) {
724
-
725
- if ( WP_Filesystem() ) {
726
- global $wp_filesystem;
727
- $upload_dir = wp_upload_dir();
728
-
729
- if ( ! $wp_filesystem->is_dir( $upload_dir['basedir'] . '/siteorigin-widgets/' ) ) {
730
- $wp_filesystem->mkdir( $upload_dir['basedir'] . '/siteorigin-widgets/' );
731
- }
732
-
733
- $wp_filesystem->delete( $upload_dir['basedir'] . '/siteorigin-widgets/' . $name );
734
- $wp_filesystem->put_contents(
735
- $upload_dir['basedir'] . '/siteorigin-widgets/' . $name,
736
- $css
737
- );
738
-
739
- } else {
740
- wp_cache_add( $name, $css, 'siteorigin_widgets' );
741
- }
742
-
743
- return $hash;
744
- }
745
-
746
- return false;
747
- }
748
-
749
- /**
750
- * Clears CSS for a specific instance
751
- */
752
- private function delete_css( $instance ){
753
- require_once ABSPATH . 'wp-admin/includes/file.php';
754
-
755
- if( WP_Filesystem() ) {
756
- global $wp_filesystem;
757
- $upload_dir = wp_upload_dir();
758
-
759
- $style = $this->get_style_name($instance);
760
- $hash = $this->get_style_hash( $instance );
761
- $name = $this->id_base.'-'.$style.'-'.$hash;
762
-
763
- $wp_filesystem->delete($upload_dir['basedir'] . '/siteorigin-widgets/' . $name . '.css');
764
- if ( in_array( $name, $this->generated_css ) ) {
765
- $index = array_search( $name, $this->generated_css );
766
- unset( $this->generated_css[$index] );
767
- //Reindex array
768
- $this->generated_css = array_values( $this->generated_css );
769
- }
770
- }
771
- }
772
-
773
- /**
774
- * Clear all old CSS files
775
- *
776
- * @var bool $force Must we force a cache refresh.
777
- */
778
- public static function clear_file_cache( $force_delete = false ){
779
- // Use this variable to ensure this only runs once per request
780
- static $done = false;
781
- if ( $done && !$force_delete ) return;
782
-
783
- if( !get_transient('sow:cleared') || $force_delete ) {
784
-
785
- require_once ABSPATH . 'wp-admin/includes/file.php';
786
- if( WP_Filesystem() ) {
787
- global $wp_filesystem;
788
- $upload_dir = wp_upload_dir();
789
-
790
- $list = $wp_filesystem->dirlist( $upload_dir['basedir'] . '/siteorigin-widgets/' );
791
- if ( ! empty( $list ) ) {
792
- foreach($list as $file) {
793
- if( $file['lastmodunix'] < time() - self::$css_expire || $force_delete ) {
794
- // Delete the file
795
- $wp_filesystem->delete( $upload_dir['basedir'] . '/siteorigin-widgets/' . $file['name'] );
796
- }
797
- }
798
- }
799
- }
800
-
801
- // Set this transient so we know when to clear all the generated CSS.
802
- set_transient('sow:cleared', true, self::$css_expire);
803
- }
804
-
805
- $done = true;
806
- }
807
-
808
- /**
809
- * Generate the CSS for the widget.
810
- *
811
- * @param $instance
812
- * @return string
813
- */
814
- public function get_instance_css( $instance ){
815
- if( !class_exists('lessc') ) require plugin_dir_path( __FILE__ ).'inc/lessc.inc.php';
816
- if( !class_exists('SiteOrigin_Widgets_Less_Functions') ) require plugin_dir_path( __FILE__ ).'inc/less-functions.php';
817
-
818
- if( !method_exists( $this, 'get_less_content' ) ) {
819
- $style_name = $this->get_style_name($instance);
820
- if( empty($style_name) ) return '';
821
-
822
- $less_file = siteorigin_widget_get_plugin_dir_path( $this->id_base ).'styles/'.$style_name . '.less';
823
- $less_file = apply_filters( 'siteorigin_widgets_less_file_' . $this->id_base, $less_file, $instance, $this );
824
-
825
- $less = ( substr( $less_file, -5 ) == '.less' && file_exists($less_file) ) ? file_get_contents( $less_file ) : '';
826
- }
827
- else {
828
- // The widget is going handle getting the instance LESS
829
- $less = $this->get_less_content( $instance );
830
- }
831
-
832
- // Substitute the variables
833
- if( !class_exists('SiteOrigin_Widgets_Color_Object') ) require plugin_dir_path( __FILE__ ) . 'inc/color.php';
834
-
835
- // Lets widgets insert their own custom generated LESS
836
- $less = preg_replace_callback( '/\.widget-function\((.*)\);/', array( $this, 'less_widget_inject' ), $less );
837
-
838
- //handle less @import statements
839
- $less = preg_replace_callback( '/^@import\s+".*?\/?([\w-\.]+)";/m', array( $this, 'get_less_import_contents' ), $less );
840
-
841
- $vars = apply_filters( 'siteorigin_widgets_less_variables_' . $this->id_base, $this->get_less_variables( $instance ), $instance, $this );
842
- if( !empty( $vars ) ){
843
- foreach($vars as $name => $value) {
844
- // Ignore empty string, false and null values (but keep '0')
845
- if( $value === '' || $value === false || $value === null ) continue;
846
-
847
- $less = preg_replace('/\@'.preg_quote($name).' *\:.*?;/', '@'.$name.': '.$value.';', $less);
848
- }
849
- }
850
-
851
- $less = apply_filters( 'siteorigin_widgets_styles', $less, $this->widget_class, $instance );
852
- $less = apply_filters( 'siteorigin_widgets_less_' . $this->id_base, $less, $instance, $this );
853
-
854
- $css = '';
855
-
856
- if( ! empty( $less ) ) {
857
- $style = $this->get_style_name( $instance );
858
- $hash = $this->get_style_hash( $instance );
859
- $css_name = $this->id_base . '-' . $style . '-' . $hash;
860
-
861
- //we assume that any remaining @imports are plain css imports and should be kept outside selectors
862
- $css_imports = '';
863
- if ( preg_match_all( '/^@import.+/m', $less, $imports ) ) {
864
- $css_imports = implode( "\n", $imports[0] );
865
- $less = preg_replace( '/^@import.+/m', '', $less );
866
- }
867
-
868
- $less = $css_imports . "\n\n" . '.so-widget-'.$css_name." { \n".$less."\n } ";
869
-
870
- $compiler = new lessc();
871
- $lc_functions = new SiteOrigin_Widgets_Less_Functions($this, $instance);
872
- $lc_functions->registerFunctions( $compiler );
873
- $compiler = apply_filters( 'siteorigin_widgets_less_compiler', $compiler, $instance, $this );
874
-
875
- try {
876
- if( method_exists( $compiler, 'compile' ) ) {
877
- $css = $compiler->compile( $less );
878
- }
879
- }
880
- catch ( Exception $e ) {
881
- if( defined( 'SITEORIGIN_WIDGETS_DEBUG' ) && SITEORIGIN_WIDGETS_DEBUG ) {
882
- throw $e;
883
- }
884
- }
885
-
886
- // Remove any attributes with default as the value
887
- $css = preg_replace('/[a-zA-Z\-]+ *: *default *;/', '', $css);
888
-
889
- // Remove any empty CSS
890
- $css = preg_replace('/[^{}]*\{\s*\}/m', '', $css);
891
- $css = trim($css);
892
- }
893
-
894
- return apply_filters( 'siteorigin_widgets_instance_css', $css, $instance, $this );
895
- }
896
-
897
- /**
898
- * Replaces LESS imports with the content from the actual files. This used as a preg callback.
899
- *
900
- * @param $matches
901
- *
902
- * @return string
903
- */
904
- private function get_less_import_contents($matches) {
905
- $filename = $matches[1];
906
-
907
- // First, we'll deal with a few special cases
908
- switch( $filename ) {
909
- case 'mixins':
910
- return file_get_contents( plugin_dir_path( __FILE__ ) . 'less/mixins.less' );
911
- break;
912
-
913
- case 'lesshat':
914
- return file_get_contents( plugin_dir_path( __FILE__ ) . 'less/lesshat.less' );
915
- break;
916
- }
917
-
918
- //get file extension
919
- preg_match( '/\.\w+$/', $filename, $ext );
920
- //if there is a file extension and it's not .less or .css we ignore
921
- if ( ! empty( $ext ) ) {
922
- if ( ! ( $ext[0] == '.less' || $ext[0] == '.css' ) ) {
923
- return '';
924
- }
925
- }
926
- else {
927
- $filename .= '.less';
928
- }
929
- //first check local widget styles directory and then bundle less directory
930
- $search_path = array(
931
- siteorigin_widget_get_plugin_dir_path( $this->id_base ) . 'styles/',
932
- plugin_dir_path( __FILE__ ) . 'less/'
933
- );
934
-
935
- foreach ( $search_path as $dir ) {
936
- if ( file_exists( $dir . $filename ) ) {
937
- return file_get_contents( $dir . $filename )."\n\n";
938
- }
939
- }
940
-
941
- //file not found
942
- return '';
943
- }
944
-
945
- /**
946
- * Used as a preg callback to replace .widget-function('some_function', ...) with output from less_some_function($instance, $args).
947
- *
948
- * @param $matches
949
- *
950
- * @return mixed|string
951
- */
952
- private function less_widget_inject($matches){
953
- // We're going to lazily split the arguments by comma
954
- $args = explode(',', $matches[1]);
955
- if( empty($args[0]) ) return '';
956
-
957
- // Shift the function name from the arguments
958
- $func = 'less_' . trim( array_shift($args) , '\'"');
959
- if( !method_exists($this, $func) ) return '';
960
-
961
- // Finally call the function and include the
962
- $args = array_map('trim', $args);
963
- return call_user_func( array($this, $func), $this->current_instance, $args );
964
- }
965
-
966
- /**
967
- * Less function for importing Google web fonts.
968
- *
969
- * @param $instance
970
- * @param $args
971
- *
972
- * @return string
973
- */
974
- function less_import_google_font($instance, $args) {
975
- if( empty( $instance ) ) return;
976
-
977
- $fonts = $this->get_google_font_fields($instance);
978
- if( empty( $fonts ) || ! is_array( $fonts ) ) return '';
979
-
980
- $font_imports = array();
981
-
982
- foreach ( $fonts as $font ) {
983
- $font_imports[] = siteorigin_widget_get_font( $font );
984
- }
985
-
986
- $import_strings = array();
987
- foreach( $font_imports as $import ) {
988
- $import_strings[] = !empty($import['css_import']) ? $import['css_import'] : '';
989
- }
990
-
991
- // Remove empty and duplicate items from the array
992
- $import_strings = array_filter( $import_strings );
993
- $import_strings = array_unique( $import_strings );
994
-
995
- return implode( "\n", $import_strings );
996
- }
997
-
998
- /**
999
- * Get any font fields which may be used by this widget.
1000
- *
1001
- * @param $instance
1002
- *
1003
- * @return array
1004
- */
1005
- function get_google_font_fields( $instance ) {
1006
- return apply_filters( 'siteorigin_widgets_google_font_fields_' . $this->id_base, array(), $instance, $this );
1007
- }
1008
-
1009
- /**
1010
- * Utility function to get a field name for a widget field.
1011
- *
1012
- * @param $field_name
1013
- * @param array $container
1014
- * @return mixed|string
1015
- */
1016
- public function so_get_field_name( $field_name, $container = array() ) {
1017
- if( empty($container) ) {
1018
- $name = $this->get_field_name( $field_name );
1019
- }
1020
- else {
1021
- // We also need to add the container fields
1022
- $container_extras = '';
1023
- foreach($container as $r) {
1024
- $container_extras .= '[' . $r['name'] . ']';
1025
-
1026
- if( $r['type'] == 'repeater' ) {
1027
- $container_extras .= '[#' . $r['name'] . '#]';
1028
- }
1029
- }
1030
-
1031
- $name = $this->get_field_name( '{{{FIELD_NAME}}}' );
1032
- $name = str_replace('[{{{FIELD_NAME}}}]', $container_extras.'[' . esc_attr($field_name) . ']', $name);
1033
- }
1034
-
1035
- $name = apply_filters( 'siteorigin_widgets_get_field_name', $name );
1036
- $name = apply_filters( 'siteorigin_widgets_get_field_name_' . $this->id_base, $name );
1037
-
1038
- return $name;
1039
- }
1040
-
1041
- /**
1042
- * Get the ID of this field.
1043
- *
1044
- * @param $field_name
1045
- * @param array $container
1046
- * @param boolean $is_template
1047
- *
1048
- * @return string
1049
- */
1050
- public function so_get_field_id( $field_name, $container = array(), $is_template = false ) {
1051
- if( empty($container) ) {
1052
- return $this->get_field_id($field_name);
1053
- }
1054
- else {
1055
- $name = array();
1056
- foreach ( $container as $container_item ) {
1057
- $name[] = $container_item['name'];
1058
- }
1059
- $name[] = $field_name;
1060
- $field_id_base = $this->get_field_id(implode('-', $name));
1061
- if ( $is_template ) {
1062
- return $field_id_base . '-_id_';
1063
- }
1064
- if ( ! isset( $this->field_ids[ $field_id_base ] ) ) {
1065
- $this->field_ids[ $field_id_base ] = 1;
1066
- }
1067
- $curId = $this->field_ids[ $field_id_base ]++;
1068
- return $field_id_base . '-' . $curId;
1069
- }
1070
- }
1071
-
1072
- /**
1073
- * Parse markdown
1074
- *
1075
- * @param $markdown
1076
- * @return string The HTML
1077
- *
1078
- * @deprecated Will be removed in version 2.0
1079
- */
1080
- function parse_markdown( $markdown ){
1081
- if( !class_exists('Parsedown') ) include plugin_dir_path(__FILE__).'inc/Parsedown.php';
1082
- $parser = new Parsedown();
1083
-
1084
- return $parser->text($markdown);
1085
- }
1086
-
1087
- /**
1088
- * Get a hash that uniquely identifies this instance.
1089
- *
1090
- * @param $instance
1091
- * @return string
1092
- */
1093
- function get_style_hash( $instance ) {
1094
- if( method_exists( $this, 'get_style_hash_variables' ) ) {
1095
- $vars = apply_filters( 'siteorigin_widgets_hash_variables_' . $this->id_base, $this->get_style_hash_variables( $instance ), $instance, $this );
1096
- } else {
1097
- $vars = apply_filters( 'siteorigin_widgets_less_variables_' . $this->id_base, $this->get_less_variables( $instance ), $instance, $this );
1098
- }
1099
- $version = property_exists( $this, 'version' ) ? $this->version : '';
1100
-
1101
- return substr( md5( json_encode( $vars ) . $version ), 0, 12 );
1102
- }
1103
-
1104
- /**
1105
- * Get the template name that we'll be using to render this widget.
1106
- *
1107
- * @param $instance
1108
- * @return mixed
1109
- */
1110
- function get_template_name( $instance ) {
1111
- return 'default';
1112
- }
1113
-
1114
- /**
1115
- * Get the name of the directory in which we should look for the template. Relative to root of widget folder.
1116
- *
1117
- * @return mixed
1118
- */
1119
- function get_template_dir( $instance ) {
1120
- return 'tpl';
1121
- }
1122
-
1123
- /**
1124
- * Get the LESS style name we'll be using for this widget.
1125
- *
1126
- * @param $instance
1127
- * @return mixed
1128
- */
1129
- function get_style_name( $instance ) {
1130
- return 'default';
1131
- }
1132
-
1133
- /**
1134
- * Get any variables that need to be substituted by
1135
- *
1136
- * @param $instance
1137
- * @return array
1138
- */
1139
- function get_less_variables( $instance ){
1140
- return array();
1141
- }
1142
-
1143
- /**
1144
- * Filter the variables we'll be storing in temporary storage for this instance if we're using `instance_storage`
1145
- *
1146
- * @param $instance
1147
- *
1148
- * @return mixed
1149
- */
1150
- function modify_stored_instance( $instance ){
1151
- return $instance;
1152
- }
1153
-
1154
- /**
1155
- * Get the stored instance based on the hash.
1156
- *
1157
- * @param $hash
1158
- *
1159
- * @return object The instance
1160
- */
1161
- function get_stored_instance( $hash ) {
1162
- return get_transient('sow_inst[' . $this->id_base . '][' . $hash . ']');
1163
- }
1164
-
1165
- /**
1166
- * This function can be overwritten to modify form values in the child widget.
1167
- *
1168
- * @param $form
1169
- * @return mixed
1170
- */
1171
- function modify_form( $form ) {
1172
- return $form;
1173
- }
1174
-
1175
-
1176
- /**
1177
- * This function can be overwritten to modify form values in the child widget.
1178
- *
1179
- * @param $child_widget_form
1180
- * @param $child_widget
1181
- * @return mixed
1182
- */
1183
- function modify_child_widget_form($child_widget_form, $child_widget) {
1184
- return $child_widget_form;
1185
- }
1186
-
1187
- /**
1188
- * This function should be overwritten by child widgets to filter an instance. Run before rendering the form and widget.
1189
- *
1190
- * @param $instance
1191
- *
1192
- * @return mixed
1193
- */
1194
- function modify_instance( $instance ){
1195
- return $instance;
1196
- }
1197
-
1198
- /**
1199
- * Can be overwritten by child widgets to make variables available to javascript via ajax calls. These are designed to be used in the admin.
1200
- */
1201
- function get_javascript_variables(){
1202
-
1203
- }
1204
-
1205
- /**
1206
- * Used by child widgets to register scripts to be enqueued for the frontend.
1207
- *
1208
- * @param array $scripts an array of scripts. Each element is an array that corresponds to wp_enqueue_script arguments
1209
- */
1210
- public function register_frontend_scripts( $scripts ){
1211
- foreach ( $scripts as $script ) {
1212
- if ( ! isset( $this->frontend_scripts[ $script[0] ] ) ) {
1213
- $this->frontend_scripts[$script[0]] = $script;
1214
- }
1215
- }
1216
- }
1217
-
1218
- /**
1219
- * Enqueue all the registered scripts
1220
- */
1221
- function enqueue_registered_scripts( $instance ) {
1222
- $f_scripts = apply_filters(
1223
- 'siteorigin_widgets_frontend_scripts_' . $this->id_base,
1224
- $this->frontend_scripts,
1225
- $instance,
1226
- $this
1227
- );
1228
-
1229
- foreach ( $f_scripts as $f_script ) {
1230
- if ( ! wp_script_is( $f_script[0] ) ) {
1231
- wp_enqueue_script(
1232
- $f_script[0],
1233
- isset( $f_script[1] ) ? $f_script[1] : false,
1234
- isset( $f_script[2] ) ? $f_script[2] : array(),
1235
- !empty( $f_script[3] ) ? $f_script[3] : SOW_BUNDLE_VERSION,
1236
- isset( $f_script[4] ) ? $f_script[4] : false
1237
- );
1238
- }
1239
- }
1240
- }
1241
-
1242
- /**
1243
- * Used by child widgets to register styles to be enqueued for the frontend.
1244
- *
1245
- * @param array $styles an array of styles. Each element is an array that corresponds to wp_enqueue_style arguments
1246
- */
1247
- public function register_frontend_styles( $styles ) {
1248
- foreach ( $styles as $style ) {
1249
- if ( ! isset( $this->frontend_styles[ $style[0] ] ) ) {
1250
- $this->frontend_styles[$style[0]] = $style;
1251
- }
1252
- }
1253
- }
1254
-
1255
- /**
1256
- * Enqueue any frontend styles that were registered
1257
- */
1258
- function enqueue_registered_styles( $instance ) {
1259
- $f_styles = apply_filters(
1260
- 'siteorigin_widgets_frontend_styles_' . $this->id_base,
1261
- $this->frontend_styles,
1262
- $instance,
1263
- $this
1264
- );
1265
-
1266
- foreach ( $f_styles as $f_style ) {
1267
- if ( ! wp_style_is( $f_style[0] ) ) {
1268
- wp_enqueue_style(
1269
- $f_style[0],
1270
- isset( $f_style[1] ) ? $f_style[1] : false,
1271
- isset( $f_style[2] ) ? $f_style[2] : array(),
1272
- !empty( $f_style[3] ) ? $f_style[3] : SOW_BUNDLE_VERSION,
1273
- isset( $f_style[4] ) ? $f_style[4] : "all"
1274
- );
1275
- }
1276
- }
1277
- }
1278
-
1279
- /**
1280
- * Can be overridden by child widgets to enqueue scripts and styles for the frontend, but child widgets should
1281
- * rather register scripts and styles using register_frontend_scripts() and register_frontend_styles(). This function
1282
- * will then ensure that the scripts are not enqueued more than once.
1283
- */
1284
- function enqueue_frontend_scripts( $instance ) {
1285
- $this->enqueue_registered_scripts( $instance );
1286
- $this->enqueue_registered_styles( $instance );
1287
-
1288
- // Give plugins a chance to enqueue additional frontend scripts
1289
- do_action('siteorigin_widgets_enqueue_frontend_scripts_' . $this->id_base, $instance, $this);
1290
- }
1291
-
1292
- /**
1293
- * Can be overwritten by child widgets to enqueue admin scripts and styles if necessary.
1294
- */
1295
- function enqueue_admin_scripts(){ }
1296
-
1297
- /**
1298
- * Check if we're currently in a preview
1299
- *
1300
- * @param array $instance
1301
- *
1302
- * @return bool
1303
- */
1304
- function is_preview( $instance = array() ) {
1305
- // Check if the instance is a preview
1306
- if( !empty( $instance[ 'is_preview' ] ) ) return true;
1307
-
1308
- // Check if the general request is a preview
1309
- $is_preview =
1310
- is_preview() || // is this a standard preview
1311
- $this->is_customize_preview() || // Is this a customizer preview
1312
- !empty( $_GET['siteorigin_panels_live_editor'] ) || // Is this a Page Builder live editor request
1313
- ( !empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'so_panels_builder_content' ); // Is this a Page Builder content ajax request
1314
-
1315
- return apply_filters( 'siteorigin_widgets_is_preview', $is_preview, $this );
1316
- }
1317
-
1318
- /**
1319
- * Whether or not so show the 'Preview' button
1320
- *
1321
- * @return bool
1322
- */
1323
- function show_preview_button(){
1324
- $show_preview = $this->widget_options['has_preview'] && ! $this->is_customize_preview();
1325
- $show_preview = apply_filters( 'siteorigin_widgets_form_show_preview_button', $show_preview, $this );
1326
- return $show_preview;
1327
- }
1328
-
1329
- /**
1330
- * Get the global settings from the options table.
1331
- *
1332
- * @return mixed
1333
- */
1334
- function get_global_settings( ){
1335
- $values = get_option( 'so_widget_settings[' . $this->widget_class . ']', array() );
1336
-
1337
- // Add in the defaults
1338
- if( $this->has_form( 'settings' ) ) {
1339
- $values = $this->add_defaults( $this->get_settings_form(), $values );
1340
- }
1341
-
1342
- return $values;
1343
- }
1344
-
1345
- /**
1346
- * Save the global settings. Handles validation too.
1347
- *
1348
- * @param array $values The new values
1349
- * @return array The sanitized values.
1350
- */
1351
- function save_global_settings( $values ){
1352
- $current = $this->get_global_settings();
1353
-
1354
- $values = $this->update( $values, $current, 'settings' );
1355
-
1356
- unset( $values['_sow_form_id'] );
1357
- update_option( 'so_widget_settings[' . $this->widget_class . ']', $values );
1358
-
1359
- return $values;
1360
- }
1361
- }
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Class SiteOrigin_Widget
5
+ *
6
+ * @author SiteOrigin <support@siteorigin.com>
7
+ */
8
+ abstract class SiteOrigin_Widget extends WP_Widget {
9
+ protected $form_options;
10
+ protected $base_folder;
11
+ protected $field_ids;
12
+ protected $fields;
13
+
14
+ /**
15
+ * The name of this widget class. Whatever the key for $wp_widgets_factory is.
16
+ *
17
+ * @var string
18
+ */
19
+ protected $widget_class;
20
+
21
+ /**
22
+ * @var array The array of registered frontend scripts
23
+ */
24
+ protected $frontend_scripts = array();
25
+
26
+ /**
27
+ * @var array The array of registered frontend styles
28
+ */
29
+ protected $frontend_styles = array();
30
+
31
+ protected $generated_css = array();
32
+ protected $current_instance;
33
+ protected $instance_storage;
34
+
35
+ /**
36
+ * @var int How many seconds a CSS file is valid for.
37
+ */
38
+ static $css_expire = 604800; // 7 days
39
+
40
+ /**
41
+ * @param string $id
42
+ * @param string $name
43
+ * @param array $widget_options Optional Normal WP_Widget widget options and a few extras.
44
+ * - help: A URL which, if present, causes a help link to be displayed on the Edit Widget modal.
45
+ * - instance_storage: Whether or not to temporarily store instances of this widget.
46
+ * - has_preview: Whether or not this widget has a preview to display. If false, the form does not output a
47
+ * 'Preview' button.
48
+ * @param array $control_options Optional Normal WP_Widget control options.
49
+ * @param array $form_options Optional An array describing the form fields used to configure SiteOrigin widgets.
50
+ * @param mixed $base_folder Optional
51
+ *
52
+ */
53
+ function __construct($id, $name, $widget_options = array(), $control_options = array(), $form_options = array(), $base_folder = false) {
54
+ $this->form_options = $form_options;
55
+ $this->base_folder = $base_folder;
56
+ $this->field_ids = array();
57
+ $this->fields = array();
58
+
59
+ $widget_options = wp_parse_args( $widget_options, array(
60
+ 'has_preview' => true,
61
+ ) );
62
+
63
+ $control_options = wp_parse_args( $control_options, array(
64
+ 'width' => 800,
65
+ ) );
66
+
67
+ if( empty( $this->widget_class ) ) {
68
+ $this->widget_class = get_class( $this );
69
+ }
70
+
71
+ parent::__construct($id, $name, $widget_options, $control_options);
72
+ $this->initialize();
73
+
74
+ // Let other plugins do additional initializing here
75
+ do_action('siteorigin_widgets_initialize_widget_' . $this->id_base, $this);
76
+ }
77
+
78
+ /**
79
+ * Initialize this widget in whatever way we need to. Run before rendering widget or form.
80
+ */
81
+ function initialize(){
82
+
83
+ }
84
+
85
+ /**
86
+ * Get the main widget form. This should be overwritten by child widgets.
87
+ *
88
+ * @return array
89
+ */
90
+ function get_widget_form(){
91
+ return method_exists( $this, 'initialize_form' ) ? $this->initialize_form() : array();
92
+ }
93
+
94
+ private function get_cached_widget_form() {
95
+ $cache_key = $this->id_base . '_form';
96
+ $form_options = wp_cache_get( $cache_key, 'siteorigin_widgets' );
97
+
98
+ if ( empty( $form_options ) ) {
99
+ $form_options = $this->get_widget_form();
100
+ wp_cache_set( $cache_key, $form_options, 'siteorigin_widgets' );
101
+ }
102
+
103
+ return $form_options;
104
+ }
105
+
106
+ /**
107
+ * Check if a child widget implements a specific form type.
108
+ *
109
+ * @param string $form_type
110
+ * @return bool
111
+ */
112
+ function has_form( $form_type = 'widget' ){
113
+ return method_exists( $this, 'get_' . $form_type . '_form' );
114
+ }
115
+
116
+ /**
117
+ * Get a specific type of form.
118
+ *
119
+ * @param $form_type
120
+ * @return array The form array, or an empty array if the form doesn't exist.
121
+ */
122
+ function get_form( $form_type ) {
123
+ return $this->has_form( $form_type ) ? call_user_func( array( $this, 'get_' . $form_type . '_form' ) ) : array();
124
+ }
125
+
126
+ /**
127
+ * Get the main form options and allow child widgets to modify that form.
128
+ *
129
+ * @param bool|SiteOrigin_Widget $parent
130
+ *
131
+ * @return mixed
132
+ */
133
+ function form_options( $parent = false ) {
134
+ if( empty( $this->form_options ) ) {
135
+ // If the widget doesn't have form_options defined from the constructor, then it might be defining them in the get_widget_form function
136
+ $this->form_options = $this->get_cached_widget_form();
137
+ }
138
+
139
+ $form_options = $this->modify_form( $this->form_options );
140
+ if( !empty($parent) ) {
141
+ $form_options = $parent->modify_child_widget_form( $form_options, $this );
142
+ }
143
+
144
+ // Give other plugins a way to modify this form.
145
+ $form_options = apply_filters( 'siteorigin_widgets_form_options', $form_options, $this );
146
+ $form_options = apply_filters( 'siteorigin_widgets_form_options_' . $this->id_base, $form_options, $this );
147
+ return $form_options;
148
+ }
149
+
150
+ /**
151
+ * Display the widget.
152
+ *
153
+ * @param array $args
154
+ * @param array $instance
155
+ */
156
+ public function widget( $args, $instance ) {
157
+ if( empty( $this->form_options ) ) {
158
+ $form_options = $this->get_cached_widget_form();
159
+ }
160
+ else {
161
+ $form_options = $this->modify_form( $this->form_options );
162
+ }
163
+
164
+ $instance = $this->modify_instance( $instance );
165
+
166
+ // Filter the instance
167
+ $instance = apply_filters( 'siteorigin_widgets_instance', $instance, $this );
168
+ $instance = apply_filters( 'siteorigin_widgets_instance_' . $this->id_base, $instance, $this );
169
+
170
+ $args = wp_parse_args( $args, array(
171
+ 'before_widget' => '',
172
+ 'after_widget' => '',
173
+ 'before_title' => '',
174
+ 'after_title' => '',
175
+ ) );
176
+
177
+ // Add any missing default values to the instance
178
+ $instance = $this->add_defaults( $form_options, $instance );
179
+
180
+ $css_name = $this->generate_and_enqueue_instance_styles( $instance );
181
+ $this->enqueue_frontend_scripts( $instance );
182
+
183
+ $template_vars = $this->get_template_variables($instance, $args);
184
+ $template_vars = apply_filters( 'siteorigin_widgets_template_variables_' . $this->id_base, $template_vars, $instance, $args, $this );
185
+
186
+ // Storage hash allows templates to get access to
187
+ $template_vars[ 'storage_hash' ] = '';
188
+ if( !empty($this->widget_options['instance_storage']) ) {
189
+ $stored_instance = $this->modify_stored_instance($instance);
190
+ // We probably don't want panels_info
191
+ unset( $stored_instance['panels_info'] );
192
+
193
+ $template_vars[ 'storage_hash' ] = substr( md5( serialize( $stored_instance ) ), 0, 8 );
194
+ if( !empty( $stored_instance ) && !$this->is_preview( $instance ) ) {
195
+ // Store this if we have a non empty instance and are not previewing
196
+ set_transient('sow_inst[' . $this->id_base . '][' . $template_vars['storage_hash'] . ']', $stored_instance, 7*86400);
197
+ }
198
+ }
199
+
200
+ if( ! method_exists( $this, 'get_html_content' ) ) {
201
+ $template_file = siteorigin_widget_get_plugin_dir_path( $this->id_base ) . $this->get_template_dir( $instance ) . '/' . $this->get_template_name( $instance ) . '.php';
202
+ $template_file = apply_filters('siteorigin_widgets_template_file_' . $this->id_base, $template_file, $instance, $this );
203
+ $template_file = realpath($template_file);
204
+
205
+ // Don't accept non PHP files
206
+ if( substr($template_file, -4) != '.php' ) $template_file = false;
207
+
208
+ ob_start();
209
+ if( !empty($template_file) && file_exists($template_file) ) {
210
+ extract( $template_vars );
211
+ @ include $template_file;
212
+ }
213
+ $template_html = ob_get_clean();
214
+
215
+ // This is a legacy, undocumented filter.
216
+ $template_html = apply_filters( 'siteorigin_widgets_template', $template_html, $this->widget_class, $instance, $this );
217
+ $template_html = apply_filters( 'siteorigin_widgets_template_html_' . $this->id_base, $template_html, $instance, $this );
218
+ }
219
+ else {
220
+ $template_html = $this->get_html_content( $instance, $args, $template_vars, $css_name );
221
+ }
222
+
223
+ $wrapper_classes = apply_filters(
224
+ 'siteorigin_widgets_wrapper_classes_' . $this->id_base,
225
+ array( 'so-widget-' . $this->id_base, 'so-widget-'.$css_name ),
226
+ $instance,
227
+ $this
228
+ );
229
+ $wrapper_classes = array_map( 'sanitize_html_class', $wrapper_classes );
230
+
231
+ $wrapper_data_string = $this->get_wrapper_data( $instance );
232
+
233
+ do_action( 'siteorigin_widgets_before_widget_' . $this->id_base, $instance, $this );
234
+ echo $args['before_widget'];
235
+ echo '<div class="' . esc_attr( implode( ' ', $wrapper_classes ) ) . '"' . $wrapper_data_string . '>';
236
+ echo $template_html;
237
+ echo '</div>';
238
+ echo $args['after_widget'];
239
+ do_action( 'siteorigin_widgets_after_widget_' . $this->id_base, $instance, $this );
240
+ }
241
+
242
+ private function get_wrapper_data( $instance ) {
243
+ $data = apply_filters(
244
+ 'siteorigin_widgets_wrapper_data_' . $this->id_base,
245
+ array(),
246
+ $instance,
247
+ $this
248
+ );
249
+ $wrapper_attr_string = '';
250
+ foreach ( $data as $name => $value ) {
251
+ $wrapper_attr_string .= ' data-' . esc_html( $name ) . '="' . esc_attr( $value ) . '"';
252
+ }
253
+
254
+ return $wrapper_attr_string;
255
+ }
256
+
257
+ /**
258
+ * Generate the CSS for this widget and display it in the appropriate way
259
+ *
260
+ * @param $instance array The instance array
261
+ *
262
+ * @return string The CSS name
263
+ */
264
+ function generate_and_enqueue_instance_styles( $instance ) {
265
+ if( empty( $form_options ) ) {
266
+ $form_options = $this->get_cached_widget_form();
267
+ }
268
+ else {
269
+ $form_options = $this->modify_form( $this->form_options );
270
+ }
271
+
272
+ // We'll assume empty instances don't have styles
273
+ if( empty($instance) ) return;
274
+
275
+ // Make sure all the default values are in place
276
+ $instance = $this->add_defaults( $form_options, $instance );
277
+
278
+ $this->current_instance = $instance;
279
+ $style = $this->get_style_name( $instance );
280
+
281
+ $upload_dir = wp_upload_dir();
282
+ $this->clear_file_cache();
283
+
284
+ if( !empty($style) ) {
285
+ $hash = $this->get_style_hash( $instance );
286
+ $css_name = $this->id_base.'-'.$style.'-'.$hash;
287
+
288
+ //Ensure styles aren't generated and enqueued more than once.
289
+ $in_preview = $this->is_preview( $instance );
290
+ if ( ! in_array( $css_name, $this->generated_css ) || $in_preview ) {
291
+ if( $in_preview ) {
292
+ siteorigin_widget_add_inline_css( $this->get_instance_css( $instance ) );
293
+ }
294
+ else {
295
+ if( !file_exists( $upload_dir['basedir'] . '/siteorigin-widgets/' . $css_name .'.css' ) || ( defined('SITEORIGIN_WIDGETS_DEBUG') && SITEORIGIN_WIDGETS_DEBUG ) ) {
296
+ // Attempt to recreate the CSS
297
+ $this->save_css( $instance );
298
+ }
299
+
300
+ if( file_exists( $upload_dir['basedir'] . '/siteorigin-widgets/' . $css_name .'.css' ) ) {
301
+ if ( ! wp_style_is( $css_name ) ) {
302
+ wp_enqueue_style(
303
+ $css_name,
304
+ set_url_scheme($upload_dir['baseurl'] . '/siteorigin-widgets/' . $css_name .'.css')
305
+ );
306
+ }
307
+ }
308
+ else {
309
+ // Fall back to using inline CSS if we can't find the cached CSS file.
310
+ // Try get the cached value.
311
+ $css = wp_cache_get( $css_name, 'siteorigin_widgets' );
312
+ if ( empty( $css ) ) {
313
+ $css = $this->get_instance_css( $instance );
314
+ }
315
+ siteorigin_widget_add_inline_css( $css );
316
+ }
317
+ }
318
+ $this->generated_css[] = $css_name;
319
+ }
320
+ }
321
+ else {
322
+ $css_name = $this->id_base.'-base';
323
+ }
324
+
325
+ $this->current_instance = false;
326
+ return $css_name;
327
+ }
328
+
329
+ private function is_customize_preview(){
330
+ global $wp_customize;
331
+ return is_a( $wp_customize, 'WP_Customize_Manager' ) && $wp_customize->is_preview();
332
+ }
333
+
334
+ /**
335
+ * Get an array of variables to make available to templates. By default, just return an array. Should be overwritten by child widgets.
336
+ *
337
+ * @param $instance
338
+ * @param $args
339
+ *
340
+ * @return array
341
+ */
342
+ public function get_template_variables( $instance, $args ){
343
+ return array();
344
+ }
345
+
346
+ /**
347
+ * Render a sub widget. This should be used inside template files.
348
+ *
349
+ * @param $class
350
+ * @param $args
351
+ * @param $instance
352
+ */
353
+ public function sub_widget($class, $args, $instance){
354
+ if(!class_exists($class)) return;
355
+ $widget = new $class;
356
+
357
+ $args['before_widget'] = '';
358
+ $args['after_widget'] = '';
359
+
360
+ $widget->widget( $args, $instance );
361
+ }
362
+
363
+ /**
364
+ * Add default values to the instance.
365
+ *
366
+ * @param $form
367
+ * @param $instance
368
+ */
369
+ function add_defaults( $form, $instance, $level = 0 ){
370
+ if( $level > 10 ) return $instance;
371
+
372
+ foreach($form as $id => $field) {
373
+
374
+ if( $field['type'] == 'repeater' ) {
375
+ if( !empty($instance[$id]) ) {
376
+ foreach( array_keys($instance[$id]) as $i ){
377
+ $instance[$id][$i] = $this->add_defaults( $field['fields'], $instance[$id][$i], $level + 1 );
378
+ }
379
+ }
380
+ }
381
+ else if( $field['type'] == 'section' ) {
382
+ if( empty($instance[$id]) ) {
383
+ $instance[$id] = array();
384
+ }
385
+ $instance[$id] = $this->add_defaults( $field['fields'], $instance[$id], $level + 1 );
386
+ }
387
+ else if( $field['type'] == 'measurement' ) {
388
+ if( ! isset( $instance[$id] ) ) {
389
+ $instance[$id] = isset( $field['default'] ) ? $field['default'] : '';
390
+ }
391
+ if ( empty( $instance[ $id . '_unit' ] ) ) {
392
+ $instance[ $id . '_unit' ] = 'px';
393
+ }
394
+ }
395
+ else if ( $field['type'] == 'order') {
396
+ if ( empty( $instance[$id] ) ) {
397
+ if( ! empty( $field['default'] ) ) {
398
+ $instance[$id] = $field['default'];
399
+ } else {
400
+ // If no default order is specified, just use the order of the options.
401
+ $instance[$id] = array_keys( $field['options'] );
402
+ }
403
+ }
404
+ }
405
+ else {
406
+ if( !isset( $instance[$id] ) ) {
407
+ $instance[$id] = isset( $field['default'] ) ? $field['default'] : '';
408
+ }
409
+ }
410
+ }
411
+
412
+ return $instance;
413
+ }
414
+
415
+ /**
416
+ * Display the widget form.
417
+ *
418
+ * @param array $instance
419
+ * @param string $form_type Which type of form we're using
420
+ *
421
+ * @return string|void
422
+ */
423
+ public function form( $instance, $form_type = 'widget' ) {
424
+ if( $form_type == 'widget' ) {
425
+ if( empty( $this->form_options ) ) {
426
+ $this->form_options = $this->form_options();
427
+ }
428
+ $form_options = $this->form_options;
429
+ }
430
+ else {
431
+ $form_options = $this->get_form( $form_type );
432
+ }
433
+
434
+ $instance = $this->modify_instance($instance);
435
+ $instance = $this->add_defaults( $form_options, $instance );
436
+
437
+ if( empty( $this->number ) ) {
438
+ // Compatibility with form widgets.
439
+ $this->number = 1;
440
+ }
441
+
442
+ // Filter the instance specifically for the form
443
+ $instance = apply_filters('siteorigin_widgets_form_instance_' . $this->id_base, $instance, $this);
444
+
445
+ // `more_entropy` adds a period to the id.
446
+ $id = str_replace( '.', '', uniqid( rand(), true ) );
447
+ $form_id = 'siteorigin_widget_form_' . md5( $id );
448
+ $class_name = str_replace( '_', '-', strtolower( $this->widget_class ) );
449
+
450
+ if( empty( $instance['_sow_form_id'] ) ) {
451
+ $instance['_sow_form_id'] = $id;
452
+ }
453
+ ?>
454
+ <div class="siteorigin-widget-form siteorigin-widget-form-main siteorigin-widget-form-main-<?php echo esc_attr($class_name) ?>" id="<?php echo $form_id ?>" data-class="<?php echo esc_attr( $this->widget_class ) ?>" style="display: none">
455
+ <?php
456
+ $this->display_teaser_message();
457
+ /* @var $field_factory SiteOrigin_Widget_Field_Factory */
458
+ $field_factory = SiteOrigin_Widget_Field_Factory::single();
459
+ $fields_javascript_variables = array();
460
+ foreach( $form_options as $field_name => $field_options ) {
461
+ /* @var $field SiteOrigin_Widget_Field_Base */
462
+ $field = $field_factory->create_field( $field_name, $field_options, $this );
463
+ $field->render( isset( $instance[$field_name] ) ? $instance[$field_name] : null, $instance );
464
+ $field_js_vars = $field->get_javascript_variables();
465
+ if( ! empty( $field_js_vars ) ) {
466
+ $fields_javascript_variables[$field_name] = $field_js_vars;
467
+ }
468
+ $field->enqueue_scripts();
469
+ $this->fields[$field_name] = $field;
470
+ }
471
+ ?>
472
+ <input type="hidden" name="<?php echo $this->so_get_field_name('_sow_form_id') ?>" value="<?php echo esc_attr( $instance['_sow_form_id'] ) ?>" class="siteorigin-widgets-form-id" />
473
+ <input type="hidden" name="<?php echo $this->so_get_field_name('_sow_form_timestamp') ?>" value="<?php echo ! empty( $instance['_sow_form_timestamp'] ) ? esc_attr( $instance['_sow_form_timestamp'] ) : '' ?>" class="siteorigin-widgets-form-timestamp" />
474
+ </div>
475
+ <div class="siteorigin-widget-form-no-styles">
476
+ <?php $this->scripts_loading_message() ?>
477
+ </div>
478
+
479
+ <?php if( $this->show_preview_button() ) : ?>
480
+ <div class="siteorigin-widget-preview" style="display: none">
481
+ <a href="#" class="siteorigin-widget-preview-button button-secondary"><?php _e('Preview', 'so-widgets-bundle') ?></a>
482
+ </div>
483
+ <?php endif; ?>
484
+
485
+ <?php if( !empty( $this->widget_options['help'] ) ) : ?>
486
+ <a href="<?php echo sow_esc_url($this->widget_options['help']) ?>" class="siteorigin-widget-help-link siteorigin-panels-help-link" target="_blank" rel="noopener noreferrer"><?php _e('Help', 'so-widgets-bundle') ?></a>
487
+ <?php endif; ?>
488
+
489
+ <script type="text/javascript">
490
+ ( function($) {
491
+ if(typeof window.sow_field_javascript_variables == 'undefined') window.sow_field_javascript_variables = {};
492
+ window.sow_field_javascript_variables["<?php echo addslashes( $this->widget_class ) ?>"] = <?php echo json_encode( $fields_javascript_variables ) ?>;
493
+
494
+ if( typeof $.fn.sowSetupForm != 'undefined' ) {
495
+ $('#<?php echo $form_id ?>').sowSetupForm();
496
+ }
497
+ else {
498
+ // Init once admin scripts have been loaded
499
+ $( document).on('sowadminloaded', function(){
500
+ $('#<?php echo $form_id ?>').sowSetupForm();
501
+ });
502
+ }
503
+ } )( jQuery );
504
+ </script>
505
+ <?php
506
+
507
+ $this->enqueue_scripts( $form_type );
508
+ }
509
+
510
+ /**
511
+ * Display the teaser message.
512
+ */
513
+ function display_teaser_message(){
514
+ if(
515
+ method_exists( $this, 'get_form_teaser' ) &&
516
+ ( $teaser = $this->get_form_teaser() )
517
+ ) {
518
+ if ( ! is_admin() ) {
519
+ wp_enqueue_style( 'dashicons' );
520
+ }
521
+
522
+ $dismissed = get_user_meta( get_current_user_id(), 'teasers_dismissed', true );
523
+ if( empty( $dismissed[ $this->id_base ] ) ) {
524
+ $dismiss_url = add_query_arg( array(
525
+ 'action' => 'so_dismiss_widget_teaser',
526
+ 'widget' => $this->id_base,
527
+ ), admin_url( 'admin-ajax.php' ) );
528
+ $dismiss_url = wp_nonce_url( $dismiss_url, 'dismiss-widget-teaser' );
529
+
530
+ ?>
531
+ <div class="siteorigin-widget-teaser">
532
+ <?php echo wp_kses_post( $teaser ) ?>
533
+ <span class="dashicons dashicons-dismiss" data-dismiss-url="<?php echo esc_url( $dismiss_url ) ?>"></span>
534
+ </div>
535
+ <?php
536
+ }
537
+ }
538
+ }
539
+
540
+ /**
541
+ * Should we display the teaser for SiteOrigin Premium
542
+ *
543
+ * @return bool
544
+ */
545
+ function display_siteorigin_premium_teaser(){
546
+ return apply_filters( 'siteorigin_premium_upgrade_teaser', true ) &&
547
+ ! defined( 'SITEORIGIN_PREMIUM_VERSION' );
548
+ }
549
+
550
+ function scripts_loading_message(){
551
+ ?>
552
+ <p><strong><?php _e('This widget has scripts and styles that need to be loaded before you can use it. Please save and reload your current page.', 'so-widgets-bundle') ?></strong></p>
553
+ <p><strong><?php _e('You will only need to do this once.', 'so-widgets-bundle') ?></strong></p>
554
+ <?php
555
+ }
556
+
557
+ /**
558
+ * Enqueue the admin scripts for the widget form.
559
+ *
560
+ * @param bool|string $form_type Should we enqueue the field scripts too?
561
+ */
562
+ function enqueue_scripts( $form_type = false ) {
563
+
564
+ if( ! wp_script_is('siteorigin-widget-admin') ) {
565
+ wp_enqueue_style( 'wp-color-picker' );
566
+ wp_enqueue_style( 'siteorigin-widget-admin', plugin_dir_url(SOW_BUNDLE_BASE_FILE).'base/css/admin.css', array( 'media-views' ), SOW_BUNDLE_VERSION );
567
+
568
+ wp_enqueue_script( 'wp-color-picker' );
569
+ wp_enqueue_media();
570
+ wp_enqueue_script(
571
+ 'siteorigin-widget-admin',
572
+ plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'base/js/admin' . SOW_BUNDLE_JS_SUFFIX . '.js',
573
+ array( 'jquery', 'jquery-ui-sortable', 'jquery-ui-slider', 'underscore' ),
574
+ SOW_BUNDLE_VERSION,
575
+ true
576
+ );
577
+
578
+ wp_localize_script( 'siteorigin-widget-admin', 'soWidgets', array(
579
+ 'ajaxurl' => wp_nonce_url( admin_url('admin-ajax.php'), 'widgets_action', '_widgets_nonce' ),
580
+ 'sure' => __('Are you sure?', 'so-widgets-bundle'),
581
+ 'backup' => array(
582
+ 'newerVersion' => __( "There is a newer version of this widget's content available.", 'so-widgets-bundle' ),
583
+ 'restore' => __( 'Restore', 'so-widgets-bundle' ),
584
+ 'dismiss' => __( 'Dismiss', 'so-widgets-bundle' ),
585
+ 'replaceWarning' => sprintf(
586
+ __( 'Clicking %s will replace the current widget contents. You can revert by refreshing the page before updating.', 'so-widgets-bundle' ),
587
+ '<em>' . __( 'Restore', 'so-widgets-bundle' ) . '</em>'
588
+ ),
589
+ ),
590
+ ) );
591
+
592
+ global $wp_customize;
593
+ if ( isset( $wp_customize ) ) {
594
+ $this->footer_admin_templates();
595
+ }
596
+ else {
597
+ add_action( 'admin_footer', array( $this, 'footer_admin_templates' ) );
598
+ }
599
+ }
600
+
601
+ if( !empty( $form_type ) && $this->has_form( $form_type ) ) {
602
+ // Enqueue field scripts for the given form type
603
+ $form_options = $this->get_form( $form_type );
604
+ $this->enqueue_field_scripts( $form_options );
605
+ }
606
+
607
+ // This lets the widget enqueue any specific admin scripts
608
+ $this->enqueue_admin_scripts();
609
+ do_action( 'siteorigin_widgets_enqueue_admin_scripts_' . $this->id_base, $this );
610
+ }
611
+
612
+ function enqueue_field_scripts( $fields ){
613
+ /* @var $field_factory SiteOrigin_Widget_Field_Factory */
614
+ $field_factory = SiteOrigin_Widget_Field_Factory::single();
615
+
616
+ foreach( $fields as $field_name => $field_options ) {
617
+ /* @var $field SiteOrigin_Widget_Field_Base */
618
+ $field = $field_factory->create_field( $field_name, $field_options, $this );
619
+ $field->enqueue_scripts();
620
+
621
+ if( !empty( $field_options['fields'] ) ) {
622
+ $this->enqueue_field_scripts( $field_options['fields'] );
623
+ }
624
+ }
625
+ }
626
+
627
+ /**
628
+ * Display all the admin stuff for the footer
629
+ */
630
+ function footer_admin_templates(){
631
+ ?>
632
+ <script type="text/template" id="so-widgets-bundle-tpl-preview-dialog">
633
+ <div class="so-widgets-dialog">
634
+ <div class="so-widgets-dialog-overlay"></div>
635
+
636
+ <div class="so-widgets-toolbar">
637
+ <h3><?php _e( 'Widget Preview', 'so-widgets-bundle' ) ?></h3>
638
+ <div class="close"><span class="dashicons dashicons-arrow-left-alt2"></span></div>
639
+ </div>
640
+
641
+ <div class="so-widgets-dialog-frame">
642
+ <iframe name="siteorigin-widgets-preview-iframe" id="siteorigin-widget-preview-iframe" style="visibility: hidden"></iframe>
643
+ </div>
644
+
645
+ <form target="siteorigin-widgets-preview-iframe" action="<?php echo wp_nonce_url( admin_url('admin-ajax.php'), 'widgets_action', '_widgets_nonce' ) ?>" method="post">
646
+ <input type="hidden" name="action" value="so_widgets_preview" />
647
+ <input type="hidden" name="data" value="" />
648
+ <input type="hidden" name="class" value="" />
649
+ </form>
650
+
651
+ </div>
652
+ </script>
653
+ <?php
654
+
655
+ // Give other plugins a chance to add their own
656
+ do_action('siteorigin_widgets_footer_admin_templates');
657
+ }
658
+
659
+ /**
660
+ * Update the widget instance.
661
+ *
662
+ * @param array $new_instance
663
+ * @param array $old_instance
664
+ * @param string $form_type The type of form we're using.
665
+ * @return array|void
666
+ */
667
+ public function update( $new_instance, $old_instance, $form_type = 'widget' ) {
668
+ if( !class_exists('SiteOrigin_Widgets_Color_Object') ) require plugin_dir_path( __FILE__ ).'inc/color.php';
669
+
670
+ if( $form_type == 'widget' ) {
671
+ if( empty( $this->form_options ) ) {
672
+ $this->form_options = $this->form_options();
673
+ }
674
+ $form_options = $this->form_options;
675
+ }
676
+ else {
677
+ $form_options = $this->get_form( $form_type );
678
+ }
679
+
680
+ if( ! empty( $form_options ) ) {
681
+ /* @var $field_factory SiteOrigin_Widget_Field_Factory */
682
+ $field_factory = SiteOrigin_Widget_Field_Factory::single();
683
+ foreach ( $form_options as $field_name => $field_options ) {
684
+ /* @var $field SiteOrigin_Widget_Field_Base */
685
+ if ( !empty( $this->fields ) && !empty( $this->fields[$field_name] ) ) {
686
+ $field = $this->fields[$field_name];
687
+ }
688
+ else {
689
+ $field = $field_factory->create_field( $field_name, $field_options, $this );
690
+ $this->fields[$field_name] = $field;
691
+ }
692
+ $new_instance[$field_name] = $field->sanitize(
693
+ isset( $new_instance[$field_name] ) ? $new_instance[$field_name] : null,
694
+ $new_instance,
695
+ isset( $old_instance[$field_name] ) ? $old_instance[$field_name] : null
696
+ );
697
+ $new_instance = $field->sanitize_instance( $new_instance );
698
+ }
699
+
700
+ // Let other plugins also sanitize the instance
701
+ $new_instance = apply_filters( 'siteorigin_widgets_sanitize_instance', $new_instance, $form_options, $this );
702
+ $new_instance = apply_filters( 'siteorigin_widgets_sanitize_instance_' . $this->id_base, $new_instance, $form_options, $this );
703
+ }
704
+
705
+ // Remove the old CSS, it'll be regenerated on page load.
706
+ $this->delete_css( $this->modify_instance( $new_instance ) );
707
+ return $new_instance;
708
+ }
709
+
710
+ /**
711
+ * Save the CSS to the filesystem
712
+ *
713
+ * @param $instance
714
+ * @return bool|string
715
+ */
716
+ private function save_css( $instance ){
717
+ require_once ABSPATH . 'wp-admin/includes/file.php';
718
+
719
+ $style = $this->get_style_name($instance);
720
+ $hash = $this->get_style_hash( $instance );
721
+ $name = $this->id_base.'-'.$style.'-'.$hash.'.css';
722
+
723
+ $css = $this->get_instance_css($instance);
724
+
725
+ if( !empty($css) ) {
726
+
727
+ if ( WP_Filesystem() ) {
728
+ global $wp_filesystem;
729
+ $upload_dir = wp_upload_dir();
730
+
731
+ if ( ! $wp_filesystem->is_dir( $upload_dir['basedir'] . '/siteorigin-widgets/' ) ) {
732
+ $wp_filesystem->mkdir( $upload_dir['basedir'] . '/siteorigin-widgets/' );
733
+ }
734
+
735
+ $wp_filesystem->delete( $upload_dir['basedir'] . '/siteorigin-widgets/' . $name );
736
+ $wp_filesystem->put_contents(
737
+ $upload_dir['basedir'] . '/siteorigin-widgets/' . $name,
738
+ $css
739
+ );
740
+
741
+ } else {
742
+ wp_cache_add( $name, $css, 'siteorigin_widgets' );
743
+ }
744
+
745
+ return $hash;
746
+ }
747
+
748
+ return false;
749
+ }
750
+
751
+ /**
752
+ * Clears CSS for a specific instance
753
+ */
754
+ private function delete_css( $instance ){
755
+ require_once ABSPATH . 'wp-admin/includes/file.php';
756
+
757
+ if( WP_Filesystem() ) {
758
+ global $wp_filesystem;
759
+ $upload_dir = wp_upload_dir();
760
+
761
+ $style = $this->get_style_name($instance);
762
+ $hash = $this->get_style_hash( $instance );
763
+ $name = $this->id_base.'-'.$style.'-'.$hash;
764
+
765
+ $wp_filesystem->delete($upload_dir['basedir'] . '/siteorigin-widgets/' . $name . '.css');
766
+ if ( in_array( $name, $this->generated_css ) ) {
767
+ $index = array_search( $name, $this->generated_css );
768
+ unset( $this->generated_css[$index] );
769
+ //Reindex array
770
+ $this->generated_css = array_values( $this->generated_css );
771
+ }
772
+ }
773
+ }
774
+
775
+ /**
776
+ * Clear all old CSS files
777
+ *
778
+ * @var bool $force Must we force a cache refresh.
779
+ */
780
+ public static function clear_file_cache( $force_delete = false ){
781
+ // Use this variable to ensure this only runs once per request
782
+ static $done = false;
783
+ if ( $done && !$force_delete ) return;
784
+
785
+ if( !get_transient('sow:cleared') || $force_delete ) {
786
+
787
+ require_once ABSPATH . 'wp-admin/includes/file.php';
788
+ if( WP_Filesystem() ) {
789
+ global $wp_filesystem;
790
+ $upload_dir = wp_upload_dir();
791
+
792
+ $list = $wp_filesystem->dirlist( $upload_dir['basedir'] . '/siteorigin-widgets/' );
793
+ if ( ! empty( $list ) ) {
794
+ foreach($list as $file) {
795
+ if( $file['lastmodunix'] < time() - self::$css_expire || $force_delete ) {
796
+ // Delete the file
797
+ $wp_filesystem->delete( $upload_dir['basedir'] . '/siteorigin-widgets/' . $file['name'] );
798
+ }
799
+ }
800
+ }
801
+ }
802
+
803
+ // Set this transient so we know when to clear all the generated CSS.
804
+ set_transient('sow:cleared', true, self::$css_expire);
805
+ }
806
+
807
+ $done = true;
808
+ }
809
+
810
+ /**
811
+ * Generate the CSS for the widget.
812
+ *
813
+ * @param $instance
814
+ * @return string
815
+ */
816
+ public function get_instance_css( $instance ){
817
+ if( !class_exists( 'SiteOrigin_LessC' ) ) require plugin_dir_path( __FILE__ ) . 'inc/lessc.inc.php';
818
+ if( !class_exists('SiteOrigin_Widgets_Less_Functions') ) require plugin_dir_path( __FILE__ ).'inc/less-functions.php';
819
+
820
+ if( !method_exists( $this, 'get_less_content' ) ) {
821
+ $style_name = $this->get_style_name($instance);
822
+ if( empty($style_name) ) return '';
823
+
824
+ $less_file = siteorigin_widget_get_plugin_dir_path( $this->id_base ).'styles/'.$style_name . '.less';
825
+ $less_file = apply_filters( 'siteorigin_widgets_less_file_' . $this->id_base, $less_file, $instance, $this );
826
+
827
+ $less = ( substr( $less_file, -5 ) == '.less' && file_exists($less_file) ) ? file_get_contents( $less_file ) : '';
828
+ }
829
+ else {
830
+ // The widget is going handle getting the instance LESS
831
+ $less = $this->get_less_content( $instance );
832
+ }
833
+
834
+ // Substitute the variables
835
+ if( !class_exists('SiteOrigin_Widgets_Color_Object') ) require plugin_dir_path( __FILE__ ) . 'inc/color.php';
836
+
837
+ // Lets widgets insert their own custom generated LESS
838
+ $less = preg_replace_callback( '/\.widget-function\((.*)\);/', array( $this, 'less_widget_inject' ), $less );
839
+
840
+ //handle less @import statements
841
+ $less = preg_replace_callback( '/^@import\s+".*?\/?([\w-\.]+)";/m', array( $this, 'get_less_import_contents' ), $less );
842
+
843
+ $vars = apply_filters( 'siteorigin_widgets_less_variables_' . $this->id_base, $this->get_less_variables( $instance ), $instance, $this );
844
+ if( !empty( $vars ) ){
845
+ foreach($vars as $name => $value) {
846
+ // Ignore empty string, false and null values (but keep '0')
847
+ if( $value === '' || $value === false || $value === null ) continue;
848
+
849
+ $less = preg_replace('/\@'.preg_quote($name).' *\:.*?;/', '@'.$name.': '.$value.';', $less);
850
+ }
851
+ }
852
+
853
+ $less = apply_filters( 'siteorigin_widgets_styles', $less, $this->widget_class, $instance );
854
+ $less = apply_filters( 'siteorigin_widgets_less_' . $this->id_base, $less, $instance, $this );
855
+
856
+ $css = '';
857
+
858
+ if( ! empty( $less ) ) {
859
+ $style = $this->get_style_name( $instance );
860
+ $hash = $this->get_style_hash( $instance );
861
+ $css_name = $this->id_base . '-' . $style . '-' . $hash;
862
+
863
+ //we assume that any remaining @imports are plain css imports and should be kept outside selectors
864
+ $css_imports = '';
865
+ if ( preg_match_all( '/^@import.+/m', $less, $imports ) ) {
866
+ $css_imports = implode( "\n", $imports[0] );
867
+ $less = preg_replace( '/^@import.+/m', '', $less );
868
+ }
869
+
870
+ $less = $css_imports . "\n\n" . '.so-widget-'.$css_name." { \n".$less."\n } ";
871
+
872
+ $compiler = new SiteOrigin_LessC();
873
+ $lc_functions = new SiteOrigin_Widgets_Less_Functions($this, $instance);
874
+ $lc_functions->registerFunctions( $compiler );
875
+ $compiler = apply_filters( 'siteorigin_widgets_less_compiler', $compiler, $instance, $this );
876
+
877
+ try {
878
+ if( method_exists( $compiler, 'compile' ) ) {
879
+ $css = $compiler->compile( $less );
880
+ }
881
+ }
882
+ catch ( Exception $e ) {
883
+ if( defined( 'SITEORIGIN_WIDGETS_DEBUG' ) && SITEORIGIN_WIDGETS_DEBUG ) {
884
+ throw $e;
885
+ }
886
+ }
887
+
888
+ // Remove any attributes with default as the value
889
+ $css = preg_replace('/[a-zA-Z\-]+ *: *default *;/', '', $css);
890
+
891
+ // Remove any empty CSS
892
+ $css = preg_replace('/[^{}]*\{\s*\}/m', '', $css);
893
+ $css = trim($css);
894
+ }
895
+
896
+ return apply_filters( 'siteorigin_widgets_instance_css', $css, $instance, $this );
897
+ }
898
+
899
+ /**
900
+ * Replaces LESS imports with the content from the actual files. This used as a preg callback.
901
+ *
902
+ * @param $matches
903
+ *
904
+ * @return string
905
+ */
906
+ private function get_less_import_contents($matches) {
907
+ $filename = $matches[1];
908
+
909
+ // First, we'll deal with a few special cases
910
+ switch( $filename ) {
911
+ case 'mixins':
912
+ return file_get_contents( plugin_dir_path( __FILE__ ) . 'less/mixins.less' );
913
+ break;
914
+
915
+ case 'lesshat':
916
+ return file_get_contents( plugin_dir_path( __FILE__ ) . 'less/lesshat.less' );
917
+ break;
918
+ }
919
+
920
+ //get file extension
921
+ preg_match( '/\.\w+$/', $filename, $ext );
922
+ //if there is a file extension and it's not .less or .css we ignore
923
+ if ( ! empty( $ext ) ) {
924
+ if ( ! ( $ext[0] == '.less' || $ext[0] == '.css' ) ) {
925
+ return '';
926
+ }
927
+ }
928
+ else {
929
+ $filename .= '.less';
930
+ }
931
+ //first check local widget styles directory and then bundle less directory
932
+ $search_path = array(
933
+ siteorigin_widget_get_plugin_dir_path( $this->id_base ) . 'styles/',
934
+ plugin_dir_path( __FILE__ ) . 'less/'
935
+ );
936
+
937
+ foreach ( $search_path as $dir ) {
938
+ if ( file_exists( $dir . $filename ) ) {
939
+ return file_get_contents( $dir . $filename )."\n\n";
940
+ }
941
+ }
942
+
943
+ //file not found
944
+ return '';
945
+ }
946
+
947
+ /**
948
+ * Used as a preg callback to replace .widget-function('some_function', ...) with output from less_some_function($instance, $args).
949
+ *
950
+ * @param $matches
951
+ *
952
+ * @return mixed|string
953
+ */
954
+ private function less_widget_inject($matches){
955
+ // We're going to lazily split the arguments by comma
956
+ $args = explode(',', $matches[1]);
957
+ if( empty($args[0]) ) return '';
958
+
959
+ // Shift the function name from the arguments
960
+ $func = 'less_' . trim( array_shift($args) , '\'"');
961
+ if( !method_exists($this, $func) ) return '';
962
+
963
+ // Finally call the function and include the
964
+ $args = array_map('trim', $args);
965
+ return call_user_func( array($this, $func), $this->current_instance, $args );
966
+ }
967
+
968
+ /**
969
+ * Less function for importing Google web fonts.
970
+ *
971
+ * @param $instance
972
+ * @param $args
973
+ *
974
+ * @return string
975
+ */
976
+ function less_import_google_font($instance, $args) {
977
+ if( empty( $instance ) ) return;
978
+
979
+ $fonts = $this->get_google_font_fields($instance);
980
+ if( empty( $fonts ) || ! is_array( $fonts ) ) return '';
981
+
982
+ $font_imports = array();
983
+
984
+ foreach ( $fonts as $font ) {
985
+ $font_imports[] = siteorigin_widget_get_font( $font );
986
+ }
987
+
988
+ $import_strings = array();
989
+ foreach( $font_imports as $import ) {
990
+ $import_strings[] = !empty($import['css_import']) ? $import['css_import'] : '';
991
+ }
992
+
993
+ // Remove empty and duplicate items from the array
994
+ $import_strings = array_filter( $import_strings );
995
+ $import_strings = array_unique( $import_strings );
996
+
997
+ return implode( "\n", $import_strings );
998
+ }
999
+
1000
+ /**
1001
+ * Get any font fields which may be used by this widget.
1002
+ *
1003
+ * @param $instance
1004
+ *
1005
+ * @return array
1006
+ */
1007
+ function get_google_font_fields( $instance ) {
1008
+ return apply_filters( 'siteorigin_widgets_google_font_fields_' . $this->id_base, array(), $instance, $this );
1009
+ }
1010
+
1011
+ /**
1012
+ * Utility function to get a field name for a widget field.
1013
+ *
1014
+ * @param $field_name
1015
+ * @param array $container
1016
+ * @return mixed|string
1017
+ */
1018
+ public function so_get_field_name( $field_name, $container = array() ) {
1019
+ if( empty($container) ) {
1020
+ $name = $this->get_field_name( $field_name );
1021
+ }
1022
+ else {
1023
+ // We also need to add the container fields
1024
+ $container_extras = '';
1025
+ foreach($container as $r) {
1026
+ $container_extras .= '[' . $r['name'] . ']';
1027
+
1028
+ if( $r['type'] == 'repeater' ) {
1029
+ $container_extras .= '[#' . $r['name'] . '#]';
1030
+ }
1031
+ }
1032
+
1033
+ $name = $this->get_field_name( '{{{FIELD_NAME}}}' );
1034
+ $name = str_replace('[{{{FIELD_NAME}}}]', $container_extras.'[' . esc_attr($field_name) . ']', $name);
1035
+ }
1036
+
1037
+ $name = apply_filters( 'siteorigin_widgets_get_field_name', $name );
1038
+ $name = apply_filters( 'siteorigin_widgets_get_field_name_' . $this->id_base, $name );
1039
+
1040
+ return $name;
1041
+ }
1042
+
1043
+ /**
1044
+ * Get the ID of this field.
1045
+ *
1046
+ * @param $field_name
1047
+ * @param array $container
1048
+ * @param boolean $is_template
1049
+ *
1050
+ * @return string
1051
+ */
1052
+ public function so_get_field_id( $field_name, $container = array(), $is_template = false ) {
1053
+ if( empty($container) ) {
1054
+ return $this->get_field_id($field_name);
1055
+ }
1056
+ else {
1057
+ $name = array();
1058
+ foreach ( $container as $container_item ) {
1059
+ $name[] = $container_item['name'];
1060
+ }
1061
+ $name[] = $field_name;
1062
+ $field_id_base = $this->get_field_id(implode('-', $name));
1063
+ if ( $is_template ) {
1064
+ return $field_id_base . '-_id_';
1065
+ }
1066
+ if ( ! isset( $this->field_ids[ $field_id_base ] ) ) {
1067
+ $this->field_ids[ $field_id_base ] = 1;
1068
+ }
1069
+ $curId = $this->field_ids[ $field_id_base ]++;
1070
+ return $field_id_base . '-' . $curId;
1071
+ }
1072
+ }
1073
+
1074
+ /**
1075
+ * Parse markdown
1076
+ *
1077
+ * @param $markdown
1078
+ * @return string The HTML
1079
+ *
1080
+ * @deprecated Will be removed in version 2.0
1081
+ */
1082
+ function parse_markdown( $markdown ){
1083
+ if( !class_exists('Parsedown') ) include plugin_dir_path(__FILE__).'inc/Parsedown.php';
1084
+ $parser = new Parsedown();
1085
+
1086
+ return $parser->text($markdown);
1087
+ }
1088
+
1089
+ /**
1090
+ * Get a hash that uniquely identifies this instance.
1091
+ *
1092
+ * @param $instance
1093
+ * @return string
1094
+ */
1095
+ function get_style_hash( $instance ) {
1096
+ if( method_exists( $this, 'get_style_hash_variables' ) ) {
1097
+ $vars = apply_filters( 'siteorigin_widgets_hash_variables_' . $this->id_base, $this->get_style_hash_variables( $instance ), $instance, $this );
1098
+ } else {
1099
+ $vars = apply_filters( 'siteorigin_widgets_less_variables_' . $this->id_base, $this->get_less_variables( $instance ), $instance, $this );
1100
+ }
1101
+ $version = property_exists( $this, 'version' ) ? $this->version : '';
1102
+
1103
+ return substr( md5( json_encode( $vars ) . $version ), 0, 12 );
1104
+ }
1105
+
1106
+ /**
1107
+ * Get the template name that we'll be using to render this widget.
1108
+ *
1109
+ * @param $instance
1110
+ * @return mixed
1111
+ */
1112
+ function get_template_name( $instance ) {
1113
+ return 'default';
1114
+ }
1115
+
1116
+ /**
1117
+ * Get the name of the directory in which we should look for the template. Relative to root of widget folder.
1118
+ *
1119
+ * @return mixed
1120
+ */
1121
+ function get_template_dir( $instance ) {
1122
+ return 'tpl';
1123
+ }
1124
+
1125
+ /**
1126
+ * Get the LESS style name we'll be using for this widget.
1127
+ *
1128
+ * @param $instance
1129
+ * @return mixed
1130
+ */
1131
+ function get_style_name( $instance ) {
1132
+ return 'default';
1133
+ }
1134
+
1135
+ /**
1136
+ * Get any variables that need to be substituted by
1137
+ *
1138
+ * @param $instance
1139
+ * @return array
1140
+ */
1141
+ function get_less_variables( $instance ){
1142
+ return array();
1143
+ }
1144
+
1145
+ /**
1146
+ * Filter the variables we'll be storing in temporary storage for this instance if we're using `instance_storage`
1147
+ *
1148
+ * @param $instance
1149
+ *
1150
+ * @return mixed
1151
+ */
1152
+ function modify_stored_instance( $instance ){
1153
+ return $instance;
1154
+ }
1155
+
1156
+ /**
1157
+ * Get the stored instance based on the hash.
1158
+ *
1159
+ * @param $hash
1160
+ *
1161
+ * @return object The instance
1162
+ */
1163
+ function get_stored_instance( $hash ) {
1164
+ return get_transient('sow_inst[' . $this->id_base . '][' . $hash . ']');
1165
+ }
1166
+
1167
+ /**
1168
+ * This function can be overwritten to modify form values in the child widget.
1169
+ *
1170
+ * @param $form
1171
+ * @return mixed
1172
+ */
1173
+ function modify_form( $form ) {
1174
+ return $form;
1175
+ }
1176
+
1177
+
1178
+ /**
1179
+ * This function can be overwritten to modify form values in the child widget.
1180
+ *
1181
+ * @param $child_widget_form
1182
+ * @param $child_widget
1183
+ * @return mixed
1184
+ */
1185
+ function modify_child_widget_form($child_widget_form, $child_widget) {
1186
+ return $child_widget_form;
1187
+ }
1188
+
1189
+ /**
1190
+ * This function should be overwritten by child widgets to filter an instance. Run before rendering the form and widget.
1191
+ *
1192
+ * @param $instance
1193
+ *
1194
+ * @return mixed
1195
+ */
1196
+ function modify_instance( $instance ){
1197
+ return $instance;
1198
+ }
1199
+
1200
+ /**
1201
+ * Can be overwritten by child widgets to make variables available to javascript via ajax calls. These are designed to be used in the admin.
1202
+ */
1203
+ function get_javascript_variables(){
1204
+
1205
+ }
1206
+
1207
+ /**
1208
+ * Used by child widgets to register scripts to be enqueued for the frontend.
1209
+ *
1210
+ * @param array $scripts an array of scripts. Each element is an array that corresponds to wp_enqueue_script arguments
1211
+ */
1212
+ public function register_frontend_scripts( $scripts ){
1213
+ foreach ( $scripts as $script ) {
1214
+ if ( ! isset( $this->frontend_scripts[ $script[0] ] ) ) {
1215
+ $this->frontend_scripts[$script[0]] = $script;
1216
+ }
1217
+ }
1218
+ }
1219
+
1220
+ /**
1221
+ * Enqueue all the registered scripts
1222
+ */
1223
+ function enqueue_registered_scripts( $instance ) {
1224
+ $f_scripts = apply_filters(
1225
+ 'siteorigin_widgets_frontend_scripts_' . $this->id_base,
1226
+ $this->frontend_scripts,
1227
+ $instance,
1228
+ $this
1229
+ );
1230
+
1231
+ foreach ( $f_scripts as $f_script ) {
1232
+ if ( ! wp_script_is( $f_script[0] ) ) {
1233
+ wp_enqueue_script(
1234
+ $f_script[0],
1235
+ isset( $f_script[1] ) ? $f_script[1] : false,
1236
+ isset( $f_script[2] ) ? $f_script[2] : array(),
1237
+ !empty( $f_script[3] ) ? $f_script[3] : SOW_BUNDLE_VERSION,
1238
+ isset( $f_script[4] ) ? $f_script[4] : false
1239
+ );
1240
+ }
1241
+ }
1242
+ }
1243
+
1244
+ /**
1245
+ * Used by child widgets to register styles to be enqueued for the frontend.
1246
+ *
1247
+ * @param array $styles an array of styles. Each element is an array that corresponds to wp_enqueue_style arguments
1248
+ */
1249
+ public function register_frontend_styles( $styles ) {
1250
+ foreach ( $styles as $style ) {
1251
+ if ( ! isset( $this->frontend_styles[ $style[0] ] ) ) {
1252
+ $this->frontend_styles[$style[0]] = $style;
1253
+ }
1254
+ }
1255
+ }
1256
+
1257
+ /**
1258
+ * Enqueue any frontend styles that were registered
1259
+ */
1260
+ function enqueue_registered_styles( $instance ) {
1261
+ $f_styles = apply_filters(
1262
+ 'siteorigin_widgets_frontend_styles_' . $this->id_base,
1263
+ $this->frontend_styles,
1264
+ $instance,
1265
+ $this
1266
+ );
1267
+
1268
+ foreach ( $f_styles as $f_style ) {
1269
+ if ( ! wp_style_is( $f_style[0] ) ) {
1270
+ wp_enqueue_style(
1271
+ $f_style[0],
1272
+ isset( $f_style[1] ) ? $f_style[1] : false,
1273
+ isset( $f_style[2] ) ? $f_style[2] : array(),
1274
+ !empty( $f_style[3] ) ? $f_style[3] : SOW_BUNDLE_VERSION,
1275
+ isset( $f_style[4] ) ? $f_style[4] : "all"
1276
+ );
1277
+ }
1278
+ }
1279
+ }
1280
+
1281
+ /**
1282
+ * Can be overridden by child widgets to enqueue scripts and styles for the frontend, but child widgets should
1283
+ * rather register scripts and styles using register_frontend_scripts() and register_frontend_styles(). This function
1284
+ * will then ensure that the scripts are not enqueued more than once.
1285
+ */
1286
+ function enqueue_frontend_scripts( $instance ) {
1287
+ $this->enqueue_registered_scripts( $instance );
1288
+ $this->enqueue_registered_styles( $instance );
1289
+
1290
+ // Give plugins a chance to enqueue additional frontend scripts
1291
+ do_action('siteorigin_widgets_enqueue_frontend_scripts_' . $this->id_base, $instance, $this);
1292
+ }
1293
+
1294
+ /**
1295
+ * Can be overwritten by child widgets to enqueue admin scripts and styles if necessary.
1296
+ */
1297
+ function enqueue_admin_scripts(){ }
1298
+
1299
+ /**
1300
+ * Check if we're currently in a preview
1301
+ *
1302
+ * @param array $instance
1303
+ *
1304
+ * @return bool
1305
+ */
1306
+ function is_preview( $instance = array() ) {
1307
+ // Check if the instance is a preview
1308
+ if( !empty( $instance[ 'is_preview' ] ) ) return true;
1309
+
1310
+ // Check if the general request is a preview
1311
+ $is_preview =
1312
+ is_preview() || // is this a standard preview
1313
+ $this->is_customize_preview() || // Is this a customizer preview
1314
+ !empty( $_GET['siteorigin_panels_live_editor'] ) || // Is this a Page Builder live editor request
1315
+ ( !empty( $_REQUEST['action'] ) && $_REQUEST['action'] == 'so_panels_builder_content' ); // Is this a Page Builder content ajax request
1316
+
1317
+ return apply_filters( 'siteorigin_widgets_is_preview', $is_preview, $this );
1318
+ }
1319
+
1320
+ /**
1321
+ * Whether or not so show the 'Preview' button
1322
+ *
1323
+ * @return bool
1324
+ */
1325
+ function show_preview_button(){
1326
+ $show_preview = $this->widget_options['has_preview'] && ! $this->is_customize_preview();
1327
+ $show_preview = apply_filters( 'siteorigin_widgets_form_show_preview_button', $show_preview, $this );
1328
+ return $show_preview;
1329
+ }
1330
+
1331
+ /**
1332
+ * Get the global settings from the options table.
1333
+ *
1334
+ * @return mixed
1335
+ */
1336
+ function get_global_settings( ){
1337
+ $values = get_option( 'so_widget_settings[' . $this->widget_class . ']', array() );
1338
+
1339
+ // Add in the defaults
1340
+ if( $this->has_form( 'settings' ) ) {
1341
+ $values = $this->add_defaults( $this->get_settings_form(), $values );
1342
+ }
1343
+
1344
+ return $values;
1345
+ }
1346
+
1347
+ /**
1348
+ * Save the global settings. Handles validation too.
1349
+ *
1350
+ * @param array $values The new values
1351
+ * @return array The sanitized values.
1352
+ */
1353
+ function save_global_settings( $values ){
1354
+ $current = $this->get_global_settings();
1355
+
1356
+ $values = $this->update( $values, $current, 'settings' );
1357
+
1358
+ unset( $values['_sow_form_id'] );
1359
+ update_option( 'so_widget_settings[' . $this->widget_class . ']', $values );
1360
+
1361
+ return $values;
1362
+ }
1363
+ }
compat/beaver-builder/sowb-beaver-builder.js CHANGED
@@ -1,130 +1,133 @@
1
- /* globals jQuery, FLBuilder, sowb, sowbForms */
2
-
3
- var sowb = window.sowb || {};
4
-
5
- ( function($){
6
- if( typeof FLBuilder !== 'undefined') {
7
- // If you're going to override jQuery's `ready` function, at least make sure it still works. :/
8
- sowb.orig_FLBuilder_initJQueryReadyFix = FLBuilder._initJQueryReadyFix;
9
- FLBuilder._initJQueryReadyFix = function() {
10
- return;
11
- };
12
-
13
- sowb.orig_FLBuilder_getSettings = FLBuilder._getSettings;
14
-
15
- /**
16
- * Replace Beaver Builder's form data collection function with our modified version.
17
- */
18
- FLBuilder._getSettings = function(form) {
19
- FLBuilder._updateEditorFields();
20
-
21
- var data = form.serializeArray(),
22
- i = 0,
23
- k = 0,
24
- value = '',
25
- name = '',
26
- key = '',
27
- keys = [],
28
- matches = [],
29
- settings = {};
30
- var sowbWidgetValues = sowbForms.getWidgetFormValues( form.find( '.siteorigin-widget-form' ) );
31
- // Loop through the form data.
32
- for ( i = 0; i < data.length; i++ ) {
33
-
34
- value = data[ i ].value.replace( /\r/gm, '' );
35
-
36
- // Don't save text editor textareas.
37
- if ( data[ i ].name.indexOf( 'flrich' ) > -1 ) {
38
- continue;
39
- }
40
- // Support foo[]... setting keys.
41
- else if ( data[ i ].name.indexOf( '[' ) > -1 ) {
42
-
43
- name = data[ i ].name.replace( /\[(.*)\]/, '' );
44
- key = data[ i ].name.replace( name, '' );
45
- keys = [];
46
- matches = key.match( /\[[^\]]*\]/g );
47
-
48
- // Remove [] from the keys.
49
- for ( k = 0; k < matches.length; k++ ) {
50
-
51
- if ( '[]' == matches[ k ] ) {
52
- continue;
53
- }
54
-
55
- keys.push( matches[ k ].replace( /\[|\]/g, '' ) );
56
- }
57
-
58
-
59
- var f = function(object, val, head, tail) {
60
- if( tail.length == 0) {
61
- object[ head ] = val;
62
- } else {
63
- if( 'undefined' == typeof object [ head ] ) {
64
- object [ head ] = {};
65
- }
66
- f(object[ head ], val, tail.shift(), tail);
67
- }
68
- };
69
-
70
- if(keys.length > 0) {
71
-
72
- var keysCopy = keys.slice();
73
- if ( 'undefined' == typeof settings[ name ] ) {
74
- settings[ name ] = {};
75
- }
76
- f(settings[ name ], value, keysCopy.shift(), keysCopy);
77
- } else {
78
-
79
- if ( 'undefined' == typeof settings[ name ] ) {
80
- settings[ name ] = [];
81
- }
82
-
83
- settings[ name ].push( value );
84
- }
85
- }
86
- // Standard name/value pair.
87
- else {
88
- settings[ data[ i ].name ] = value;
89
- }
90
- }
91
-
92
- // Update auto suggest values.
93
- for ( key in settings ) {
94
-
95
- if ( 'undefined' != typeof settings[ 'as_values_' + key ] ) {
96
-
97
- settings[ key ] = $.grep(
98
- settings[ 'as_values_' + key ].split( ',' ),
99
- function( n ) {
100
- return n !== '';
101
- }
102
- ).join( ',' );
103
-
104
- try {
105
- delete settings[ 'as_values_' + key ];
106
- }
107
- catch( e ) {}
108
- }
109
- }
110
-
111
- if ( typeof FLBuilder._getOriginalSettings === 'function' ) {
112
- // Merge in the original settings in case legacy fields haven't rendered yet.
113
- settings = $.extend( {}, FLBuilder._getOriginalSettings( form ), settings );
114
- }
115
-
116
- settings[ name ] = sowbWidgetValues;
117
- // Return the settings.
118
- return settings;
119
- }
120
- }
121
-
122
- // To ensure necessary scripts are executed again when settings are changed
123
- $( document ).on( 'fl-builder.preview-rendered fl-builder.layout-rendered', '.fl-builder-content', function() {
124
- // Trigger Widgets Bundle widgets to setup
125
- $( sowb ).trigger( 'setup_widgets' );
126
- } );
127
-
128
- })(jQuery);
129
-
130
- window.sowb = sowb;
 
 
 
1
+ /* globals jQuery, FLBuilder, sowb, sowbForms */
2
+
3
+ var sowb = window.sowb || {};
4
+
5
+ ( function($){
6
+ if( typeof FLBuilder !== 'undefined') {
7
+ // If you're going to override jQuery's `ready` function, at least make sure it still works. :/
8
+ sowb.orig_FLBuilder_initJQueryReadyFix = FLBuilder._initJQueryReadyFix;
9
+ FLBuilder._initJQueryReadyFix = function() {
10
+ return;
11
+ };
12
+
13
+ sowb.orig_FLBuilder_getSettings = FLBuilder._getSettings;
14
+
15
+ /**
16
+ * Replace Beaver Builder's form data collection function with our modified version.
17
+ */
18
+ FLBuilder._getSettings = function(form) {
19
+ FLBuilder._updateEditorFields();
20
+
21
+ var data = form.serializeArray(),
22
+ i = 0,
23
+ k = 0,
24
+ value = '',
25
+ name = '',
26
+ key = '',
27
+ keys = [],
28
+ matches = [],
29
+ settings = {};
30
+
31
+ // Loop through the form data.
32
+ for ( i = 0; i < data.length; i++ ) {
33
+
34
+ value = data[ i ].value.replace( /\r/gm, '' );
35
+
36
+ // Don't save text editor textareas.
37
+ if ( data[ i ].name.indexOf( 'flrich' ) > -1 ) {
38
+ continue;
39
+ }
40
+ // Support foo[]... setting keys.
41
+ else if ( data[ i ].name.indexOf( '[' ) > -1 ) {
42
+
43
+ name = data[ i ].name.replace( /\[(.*)\]/, '' );
44
+ key = data[ i ].name.replace( name, '' );
45
+ keys = [];
46
+ matches = key.match( /\[[^\]]*\]/g );
47
+
48
+ // Remove [] from the keys.
49
+ for ( k = 0; k < matches.length; k++ ) {
50
+
51
+ if ( '[]' === matches[ k ] ) {
52
+ continue;
53
+ }
54
+
55
+ keys.push( matches[ k ].replace( /\[|\]/g, '' ) );
56
+ }
57
+
58
+
59
+ var f = function(object, val, head, tail) {
60
+ if( tail.length === 0) {
61
+ object[ head ] = val;
62
+ } else {
63
+ if( 'undefined' === typeof object [ head ] ) {
64
+ object [ head ] = {};
65
+ }
66
+ f(object[ head ], val, tail.shift(), tail);
67
+ }
68
+ };
69
+
70
+ if(keys.length > 0) {
71
+
72
+ var keysCopy = keys.slice();
73
+ if ( 'undefined' === typeof settings[ name ] ) {
74
+ settings[ name ] = {};
75
+ }
76
+ f(settings[ name ], value, keysCopy.shift(), keysCopy);
77
+ } else {
78
+
79
+ if ( 'undefined' === typeof settings[ name ] ) {
80
+ settings[ name ] = [];
81
+ }
82
+
83
+ settings[ name ].push( value );
84
+ }
85
+ }
86
+ // Standard name/value pair.
87
+ else {
88
+ settings[ data[ i ].name ] = value;
89
+ }
90
+ }
91
+
92
+ // Update auto suggest values.
93
+ for ( key in settings ) {
94
+
95
+ if ( 'undefined' !== typeof settings[ 'as_values_' + key ] ) {
96
+
97
+ settings[ key ] = $.grep(
98
+ settings[ 'as_values_' + key ].split( ',' ),
99
+ function( n ) {
100
+ return n !== '';
101
+ }
102
+ ).join( ',' );
103
+
104
+ try {
105
+ delete settings[ 'as_values_' + key ];
106
+ }
107
+ catch( e ) {}
108
+ }
109
+ }
110
+
111
+ if ( typeof FLBuilder._getOriginalSettings === 'function' ) {
112
+ // Merge in the original settings in case legacy fields haven't rendered yet.
113
+ settings = $.extend( {}, FLBuilder._getOriginalSettings( form ), settings );
114
+ }
115
+
116
+ var widgetForm = form.find( '.siteorigin-widget-form' );
117
+ if ( widgetForm.length ) {
118
+ settings[ name ] = sowbForms.getWidgetFormValues( widgetForm );
119
+ }
120
+ // Return the settings.
121
+ return settings;
122
+ }
123
+ }
124
+
125
+ // To ensure necessary scripts are executed again when settings are changed
126
+ $( document ).on( 'fl-builder.preview-rendered fl-builder.layout-rendered', '.fl-builder-content', function() {
127
+ // Trigger Widgets Bundle widgets to setup
128
+ $( sowb ).trigger( 'setup_widgets' );
129
+ } );
130
+
131
+ })(jQuery);
132
+
133
+ window.sowb = sowb;
compat/beaver-builder/sowb-beaver-builder.min.js CHANGED
@@ -1 +1 @@
1
- var sowb=window.sowb||{};!function(e){"undefined"!=typeof FLBuilder&&(sowb.orig_FLBuilder_initJQueryReadyFix=FLBuilder._initJQueryReadyFix,FLBuilder._initJQueryReadyFix=function(){},sowb.orig_FLBuilder_getSettings=FLBuilder._getSettings,FLBuilder._getSettings=function(i){FLBuilder._updateEditorFields();var r=i.serializeArray(),t=0,n=0,d="",l="",o="",u=[],s=[],a={},g=sowbForms.getWidgetFormValues(i.find(".siteorigin-widget-form"));for(t=0;t<r.length;t++)if(d=r[t].value.replace(/\r/gm,""),!(r[t].name.indexOf("flrich")>-1))if(r[t].name.indexOf("[")>-1){for(l=r[t].name.replace(/\[(.*)\]/,""),o=r[t].name.replace(l,""),u=[],s=o.match(/\[[^\]]*\]/g),n=0;n<s.length;n++)"[]"!=s[n]&&u.push(s[n].replace(/\[|\]/g,""));var f=function(e,i,r,t){0==t.length?e[r]=i:(void 0===e[r]&&(e[r]={}),f(e[r],i,t.shift(),t))};if(u.length>0){var c=u.slice();void 0===a[l]&&(a[l]={}),f(a[l],d,c.shift(),c)}else void 0===a[l]&&(a[l]=[]),a[l].push(d)}else a[r[t].name]=d;for(o in a)if(void 0!==a["as_values_"+o]){a[o]=e.grep(a["as_values_"+o].split(","),function(e){return""!==e}).join(",");try{delete a["as_values_"+o]}catch(e){}}return"function"==typeof FLBuilder._getOriginalSettings&&(a=e.extend({},FLBuilder._getOriginalSettings(i),a)),a[l]=g,a}),e(document).on("fl-builder.preview-rendered fl-builder.layout-rendered",".fl-builder-content",function(){e(sowb).trigger("setup_widgets")})}(jQuery),window.sowb=sowb;
1
+ var sowb=window.sowb||{};!function(e){"undefined"!=typeof FLBuilder&&(sowb.orig_FLBuilder_initJQueryReadyFix=FLBuilder._initJQueryReadyFix,FLBuilder._initJQueryReadyFix=function(){},sowb.orig_FLBuilder_getSettings=FLBuilder._getSettings,FLBuilder._getSettings=function(i){FLBuilder._updateEditorFields();var r=i.serializeArray(),t=0,n=0,l="",d="",o="",u=[],s=[],a={};for(t=0;t<r.length;t++)if(l=r[t].value.replace(/\r/gm,""),!(r[t].name.indexOf("flrich")>-1))if(r[t].name.indexOf("[")>-1){for(d=r[t].name.replace(/\[(.*)\]/,""),o=r[t].name.replace(d,""),u=[],s=o.match(/\[[^\]]*\]/g),n=0;n<s.length;n++)"[]"!==s[n]&&u.push(s[n].replace(/\[|\]/g,""));var g=function(e,i,r,t){0===t.length?e[r]=i:(void 0===e[r]&&(e[r]={}),g(e[r],i,t.shift(),t))};if(u.length>0){var f=u.slice();void 0===a[d]&&(a[d]={}),g(a[d],l,f.shift(),f)}else void 0===a[d]&&(a[d]=[]),a[d].push(l)}else a[r[t].name]=l;for(o in a)if(void 0!==a["as_values_"+o]){a[o]=e.grep(a["as_values_"+o].split(","),function(e){return""!==e}).join(",");try{delete a["as_values_"+o]}catch(e){}}"function"==typeof FLBuilder._getOriginalSettings&&(a=e.extend({},FLBuilder._getOriginalSettings(i),a));var c=i.find(".siteorigin-widget-form");return c.length&&(a[d]=sowbForms.getWidgetFormValues(c)),a}),e(document).on("fl-builder.preview-rendered fl-builder.layout-rendered",".fl-builder-content",function(){e(sowb).trigger("setup_widgets")})}(jQuery),window.sowb=sowb;
compat/elementor/elementor.php CHANGED
@@ -1,120 +1,120 @@
1
- <?php
2
-
3
- class SiteOrigin_Widgets_Bundle_Elementor {
4
-
5
- /**
6
- * Get the singleton instance
7
- *
8
- * @return SiteOrigin_Widgets_Bundle_Elementor
9
- */
10
- public static function single() {
11
- static $single;
12
-
13
- return empty( $single ) ? $single = new self() : $single;
14
- }
15
-
16
- private $plugin;
17
-
18
- function __construct() {
19
- add_action( 'admin_action_elementor', array( $this, 'init_editor' ) );
20
- add_action( 'template_redirect', array( $this, 'init_preview' ) );
21
-
22
- add_action( 'wp_ajax_elementor_render_widget', array( $this, 'ajax_render_widget_preview' ) );
23
- add_action( 'wp_ajax_elementor_editor_get_wp_widget_form', array( $this, 'ajax_render_widget_form' ) );
24
- }
25
-
26
- function init_editor() {
27
- add_action( 'elementor/editor/before_enqueue_scripts', array( $this, 'enqueue_active_widgets_scripts' ) );
28
- }
29
-
30
- function init_preview() {
31
- $this->plugin = Elementor\Plugin::instance();
32
- if ( !empty( $this->plugin->preview ) && method_exists( $this->plugin->preview, 'is_preview_mode' ) && $this->plugin->preview->is_preview_mode() ) {
33
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
34
- add_action( 'elementor/preview/enqueue_styles', array( $this, 'enqueue_preview_scripts' ) );
35
- }
36
- }
37
-
38
- function enqueue_frontend_scripts() {
39
-
40
- $post_id = get_the_ID();
41
-
42
- if( defined( 'Elementor\\DB::STATUS_DRAFT' ) && ! empty( $this->plugin->db ) && method_exists( $this->plugin->db, 'get_builder' ) ) {
43
- // This is necessary to ensure styles and scripts are enqueued. Not sure why this is enough, but I assume
44
- // Elementor is calling widgets' `widget` method with instance data in the process of retrieving editor data.
45
- $this->plugin->db->get_builder( $post_id, Elementor\DB::STATUS_DRAFT );
46
- }
47
- }
48
-
49
- function enqueue_preview_scripts() {
50
-
51
- global $wp_widget_factory;
52
-
53
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
54
- if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
55
- /* @var $widget_obj SiteOrigin_Widget */
56
- ob_start();
57
- $widget_obj->widget( array(), array() );
58
- ob_clean();
59
- }
60
- }
61
-
62
- }
63
-
64
- function enqueue_active_widgets_scripts() {
65
-
66
- add_action( 'wp_print_footer_scripts', array( $this, 'print_footer_templates' ) );
67
-
68
- global $wp_widget_factory;
69
-
70
- // Elementor does it's editing in it's own front end so enqueue required form scripts for active widgets.
71
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
72
- if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
73
- /* @var $widget_obj SiteOrigin_Widget */
74
- ob_start();
75
- $widget_obj->form( array() );
76
- ob_clean();
77
- }
78
- }
79
-
80
- wp_enqueue_style( 'sowb-styles-for-elementor', plugin_dir_url( __FILE__ ) . 'styles.css' );
81
-
82
- wp_enqueue_script(
83
- 'sowb-js-for-elementor',
84
- plugin_dir_url( __FILE__ ) . 'sowb-elementor' . SOW_BUNDLE_JS_SUFFIX . '.js',
85
- array( 'jquery' )
86
- );
87
-
88
- }
89
-
90
- function print_footer_templates() {
91
- global $wp_widget_factory;
92
-
93
- // Elementor does it's editing in the front end so print required footer templates for active widgets.
94
- foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
95
- if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
96
- /* @var $widget_obj SiteOrigin_Widget */
97
- $widget_obj->footer_admin_templates();
98
- }
99
- }
100
- }
101
-
102
- function ajax_render_widget_preview() {
103
- add_filter( 'siteorigin_widgets_is_preview', '__return_true' );
104
- add_filter( 'elementor/widget/render_content', array( $this, 'render_widget_preview' ) );
105
- }
106
-
107
- function render_widget_preview( $widget_output ) {
108
-
109
- siteorigin_widget_print_styles();
110
-
111
- return $widget_output;
112
- }
113
-
114
- function ajax_render_widget_form() {
115
- // Don't want to show the form preview button when using Elementor
116
- add_filter( 'siteorigin_widgets_form_show_preview_button', array( $this, '__return_false' ) );
117
- }
118
- }
119
-
120
- SiteOrigin_Widgets_Bundle_Elementor::single();
1
+ <?php
2
+
3
+ class SiteOrigin_Widgets_Bundle_Elementor {
4
+
5
+ /**
6
+ * Get the singleton instance
7
+ *
8
+ * @return SiteOrigin_Widgets_Bundle_Elementor
9
+ */
10
+ public static function single() {
11
+ static $single;
12
+
13
+ return empty( $single ) ? $single = new self() : $single;
14
+ }
15
+
16
+ private $plugin;
17
+
18
+ function __construct() {
19
+ add_action( 'admin_action_elementor', array( $this, 'init_editor' ) );
20
+ add_action( 'template_redirect', array( $this, 'init_preview' ) );
21
+
22
+ add_action( 'wp_ajax_elementor_render_widget', array( $this, 'ajax_render_widget_preview' ) );
23
+ add_action( 'wp_ajax_elementor_editor_get_wp_widget_form', array( $this, 'ajax_render_widget_form' ) );
24
+ }
25
+
26
+ function init_editor() {
27
+ add_action( 'elementor/editor/before_enqueue_scripts', array( $this, 'enqueue_active_widgets_scripts' ) );
28
+ }
29
+
30
+ function init_preview() {
31
+ $this->plugin = Elementor\Plugin::instance();
32
+ if ( !empty( $this->plugin->preview ) && method_exists( $this->plugin->preview, 'is_preview_mode' ) && $this->plugin->preview->is_preview_mode() ) {
33
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
34
+ add_action( 'elementor/preview/enqueue_styles', array( $this, 'enqueue_preview_scripts' ) );
35
+ }
36
+ }
37
+
38
+ function enqueue_frontend_scripts() {
39
+
40
+ $post_id = get_the_ID();
41
+
42
+ if( defined( 'Elementor\\DB::STATUS_DRAFT' ) && ! empty( $this->plugin->db ) && method_exists( $this->plugin->db, 'get_builder' ) ) {
43
+ // This is necessary to ensure styles and scripts are enqueued. Not sure why this is enough, but I assume
44
+ // Elementor is calling widgets' `widget` method with instance data in the process of retrieving editor data.
45
+ $this->plugin->db->get_builder( $post_id, Elementor\DB::STATUS_DRAFT );
46
+ }
47
+ }
48
+
49
+ function enqueue_preview_scripts() {
50
+
51
+ global $wp_widget_factory;
52
+
53
+ foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
54
+ if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
55
+ /* @var $widget_obj SiteOrigin_Widget */
56
+ ob_start();
57
+ $widget_obj->widget( array(), array() );
58
+ ob_clean();
59
+ }
60
+ }
61
+
62
+ }
63
+
64
+ function enqueue_active_widgets_scripts() {
65
+
66
+ add_action( 'wp_print_footer_scripts', array( $this, 'print_footer_templates' ) );
67
+
68
+ global $wp_widget_factory;
69
+
70
+ // Elementor does it's editing in it's own front end so enqueue required form scripts for active widgets.
71
+ foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
72
+ if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
73
+ /* @var $widget_obj SiteOrigin_Widget */
74
+ ob_start();
75
+ $widget_obj->form( array() );
76
+ ob_clean();
77
+ }
78
+ }
79
+
80
+ wp_enqueue_style( 'sowb-styles-for-elementor', plugin_dir_url( __FILE__ ) . 'styles.css' );
81
+
82
+ wp_enqueue_script(
83
+ 'sowb-js-for-elementor',
84
+ plugin_dir_url( __FILE__ ) . 'sowb-elementor' . SOW_BUNDLE_JS_SUFFIX . '.js',
85
+ array( 'jquery' )
86
+ );
87
+
88
+ }
89
+
90
+ function print_footer_templates() {
91
+ global $wp_widget_factory;
92
+
93
+ // Elementor does it's editing in the front end so print required footer templates for active widgets.
94
+ foreach ( $wp_widget_factory->widgets as $class => $widget_obj ) {
95
+ if ( ! empty( $widget_obj ) && is_object( $widget_obj ) && is_subclass_of( $widget_obj, 'SiteOrigin_Widget' ) ) {
96
+ /* @var $widget_obj SiteOrigin_Widget */
97
+ $widget_obj->footer_admin_templates();
98
+ }
99
+ }
100
+ }
101
+
102
+ function ajax_render_widget_preview() {
103
+ add_filter( 'siteorigin_widgets_is_preview', '__return_true' );
104
+ add_filter( 'elementor/widget/render_content', array( $this, 'render_widget_preview' ) );
105
+ }
106
+
107
+ function render_widget_preview( $widget_output ) {
108
+
109
+ siteorigin_widget_print_styles();
110
+
111
+ return $widget_output;
112
+ }
113
+
114
+ function ajax_render_widget_form() {
115
+ // Don't want to show the form preview button when using Elementor
116
+ add_filter( 'siteorigin_widgets_form_show_preview_button', array( $this, '__return_false' ) );
117
+ }
118
+ }
119
+
120
+ SiteOrigin_Widgets_Bundle_Elementor::single();
icons/ionicons/filter.php CHANGED
@@ -1,740 +1,740 @@
1
- <?php
2
-
3
- function siteorigin_widgets_icons_ionicons_filter( $icons ){
4
- return array_merge($icons, array(
5
- "alert" => '&#xf101',
6
- "alert-circled" => '&#xf100',
7
- "android-add" => '&#xf2c7',
8
- "android-add-circle" => '&#xf359',
9
- "android-alarm-clock" => '&#xf35a',
10
- "android-alert" => '&#xf35b',
11
- "android-apps" => '&#xf35c',
12
- "android-archive" => '&#xf2c9',
13
- "android-arrow-back" => '&#xf2ca',
14
- "android-arrow-down" => '&#xf35d',
15
- "android-arrow-dropdown" => '&#xf35f',
16
- "android-arrow-dropdown-circle" => '&#xf35e',
17
- "android-arrow-dropleft" => '&#xf361',
18
- "android-arrow-dropleft-circle" => '&#xf360',
19
- "android-arrow-dropright" => '&#xf363',
20
- "android-arrow-dropright-circle" => '&#xf362',
21
- "android-arrow-dropup" => '&#xf365',
22
- "android-arrow-dropup-circle" => '&#xf364',
23
- "android-arrow-forward" => '&#xf30f',
24
- "android-arrow-up" => '&#xf366',
25
- "android-attach" => '&#xf367',
26
- "android-bar" => '&#xf368',
27
- "android-bicycle" => '&#xf369',
28
- "android-boat" => '&#xf36a',
29
- "android-bookmark" => '&#xf36b',
30
- "android-bulb" => '&#xf36c',
31
- "android-bus" => '&#xf36d',
32
- "android-calendar" => '&#xf2d1',
33
- "android-call" => '&#xf2d2',
34
- "android-camera" => '&#xf2d3',
35
- "android-cancel" => '&#xf36e',
36
- "android-car" => '&#xf36f',
37
- "android-cart" => '&#xf370',
38
- "android-chat" => '&#xf2d4',
39
- "android-checkbox" => '&#xf374',
40
- "android-checkbox-blank" => '&#xf371',
41
- "android-checkbox-outline" => '&#xf373',
42
- "android-checkbox-outline-blank" => '&#xf372',
43
- "android-checkmark-circle" => '&#xf375',
44
- "android-clipboard" => '&#xf376',
45
- "android-close" => '&#xf2d7',
46
- "android-cloud" => '&#xf37a',
47
- "android-cloud-circle" => '&#xf377',
48
- "android-cloud-done" => '&#xf378',
49
- "android-cloud-outline" => '&#xf379',
50
- "android-color-palette" => '&#xf37b',
51
- "android-compass" => '&#xf37c',
52
- "android-contact" => '&#xf2d8',
53
- "android-contacts" => '&#xf2d9',
54
- "android-contract" => '&#xf37d',
55
- "android-create" => '&#xf37e',
56
- "android-delete" => '&#xf37f',
57
- "android-desktop" => '&#xf380',
58
- "android-document" => '&#xf381',
59
- "android-done" => '&#xf383',
60
- "android-done-all" => '&#xf382',
61
- "android-download" => '&#xf2dd',
62
- "android-drafts" => '&#xf384',
63
- "android-exit" => '&#xf385',
64
- "android-expand" => '&#xf386',
65
- "android-favorite" => '&#xf388',
66
- "android-favorite-outline" => '&#xf387',
67
- "android-film" => '&#xf389',
68
- "android-folder" => '&#xf2e0',
69
- "android-folder-open" => '&#xf38a',
70
- "android-funnel" => '&#xf38b',
71
- "android-globe" => '&#xf38c',
72
- "android-hand" => '&#xf2e3',
73
- "android-hangout" => '&#xf38d',
74
- "android-happy" => '&#xf38e',
75
- "android-home" => '&#xf38f',
76
- "android-image" => '&#xf2e4',
77
- "android-laptop" => '&#xf390',
78
- "android-list" => '&#xf391',
79
- "android-locate" => '&#xf2e9',
80
- "android-lock" => '&#xf392',
81
- "android-mail" => '&#xf2eb',
82
- "android-map" => '&#xf393',
83
- "android-menu" => '&#xf394',
84
- "android-microphone" => '&#xf2ec',
85
- "android-microphone-off" => '&#xf395',
86
- "android-more-horizontal" => '&#xf396',
87
- "android-more-vertical" => '&#xf397',
88
- "android-navigate" => '&#xf398',
89
- "android-notifications" => '&#xf39b',
90
- "android-notifications-none" => '&#xf399',
91
- "android-notifications-off" => '&#xf39a',
92
- "android-open" => '&#xf39c',
93
- "android-options" => '&#xf39d',
94
- "android-people" => '&#xf39e',
95
- "android-person" => '&#xf3a0',
96
- "android-person-add" => '&#xf39f',
97
- "android-phone-landscape" => '&#xf3a1',
98
- "android-phone-portrait" => '&#xf3a2',
99
- "android-pin" => '&#xf3a3',
100
- "android-plane" => '&#xf3a4',
101
- "android-playstore" => '&#xf2f0',
102
- "android-print" => '&#xf3a5',
103
- "android-radio-button-off" => '&#xf3a6',
104
- "android-radio-button-on" => '&#xf3a7',
105
- "android-refresh" => '&#xf3a8',
106
- "android-remove" => '&#xf2f4',
107
- "android-remove-circle" => '&#xf3a9',
108
- "android-restaurant" => '&#xf3aa',
109
- "android-sad" => '&#xf3ab',
110
- "android-search" => '&#xf2f5',
111
- "android-send" => '&#xf2f6',
112
- "android-settings" => '&#xf2f7',
113
- "android-share" => '&#xf2f8',
114
- "android-share-alt" => '&#xf3ac',
115
- "android-star" => '&#xf2fc',
116
- "android-star-half" => '&#xf3ad',
117
- "android-star-outline" => '&#xf3ae',
118
- "android-stopwatch" => '&#xf2fd',
119
- "android-subway" => '&#xf3af',
120
- "android-sunny" => '&#xf3b0',
121
- "android-sync" => '&#xf3b1',
122
- "android-textsms" => '&#xf3b2',
123
- "android-time" => '&#xf3b3',
124
- "android-train" => '&#xf3b4',
125
- "android-unlock" => '&#xf3b5',
126
- "android-upload" => '&#xf3b6',
127
- "android-volume-down" => '&#xf3b7',
128
- "android-volume-mute" => '&#xf3b8',
129
- "android-volume-off" => '&#xf3b9',
130
- "android-volume-up" => '&#xf3ba',
131
- "android-walk" => '&#xf3bb',
132
- "android-warning" => '&#xf3bc',
133
- "android-watch" => '&#xf3bd',
134
- "android-wifi" => '&#xf305',
135
- "aperture" => '&#xf313',
136
- "archive" => '&#xf102',
137
- "arrow-down-a" => '&#xf103',
138
- "arrow-down-b" => '&#xf104',
139
- "arrow-down-c" => '&#xf105',
140
- "arrow-expand" => '&#xf25e',
141
- "arrow-graph-down-left" => '&#xf25f',
142
- "arrow-graph-down-right" => '&#xf260',
143
- "arrow-graph-up-left" => '&#xf261',
144
- "arrow-graph-up-right" => '&#xf262',
145
- "arrow-left-a" => '&#xf106',
146
- "arrow-left-b" => '&#xf107',
147
- "arrow-left-c" => '&#xf108',
148
- "arrow-move" => '&#xf263',
149
- "arrow-resize" => '&#xf264',
150
- "arrow-return-left" => '&#xf265',
151
- "arrow-return-right" => '&#xf266',
152
- "arrow-right-a" => '&#xf109',
153
- "arrow-right-b" => '&#xf10a',
154
- "arrow-right-c" => '&#xf10b',
155
- "arrow-shrink" => '&#xf267',
156
- "arrow-swap" => '&#xf268',
157
- "arrow-up-a" => '&#xf10c',
158
- "arrow-up-b" => '&#xf10d',
159
- "arrow-up-c" => '&#xf10e',
160
- "asterisk" => '&#xf314',
161
- "at" => '&#xf10f',
162
- "backspace" => '&#xf3bf',
163
- "backspace-outline" => '&#xf3be',
164
- "bag" => '&#xf110',
165
- "battery-charging" => '&#xf111',
166
- "battery-empty" => '&#xf112',
167
- "battery-full" => '&#xf113',
168
- "battery-half" => '&#xf114',
169
- "battery-low" => '&#xf115',
170
- "beaker" => '&#xf269',
171
- "beer" => '&#xf26a',
172
- "bluetooth" => '&#xf116',
173
- "bonfire" => '&#xf315',
174
- "bookmark" => '&#xf26b',
175
- "bowtie" => '&#xf3c0',
176
- "briefcase" => '&#xf26c',
177
- "bug" => '&#xf2be',
178
- "calculator" => '&#xf26d',
179
- "calendar" => '&#xf117',
180
- "camera" => '&#xf118',
181
- "card" => '&#xf119',
182
- "cash" => '&#xf316',
183
- "chatbox" => '&#xf11b',
184
- "chatbox-working" => '&#xf11a',
185
- "chatboxes" => '&#xf11c',
186
- "chatbubble" => '&#xf11e',
187
- "chatbubble-working" => '&#xf11d',
188
- "chatbubbles" => '&#xf11f',
189
- "checkmark" => '&#xf122',
190
- "checkmark-circled" => '&#xf120',
191
- "checkmark-round" => '&#xf121',
192
- "chevron-down" => '&#xf123',
193
- "chevron-left" => '&#xf124',
194
- "chevron-right" => '&#xf125',
195
- "chevron-up" => '&#xf126',
196
- "clipboard" => '&#xf127',
197
- "clock" => '&#xf26e',
198
- "close" => '&#xf12a',
199
- "close-circled" => '&#xf128',
200
- "close-round" => '&#xf129',
201
- "closed-captioning" => '&#xf317',
202
- "cloud" => '&#xf12b',
203
- "code" => '&#xf271',
204
- "code-download" => '&#xf26f',
205
- "code-working" => '&#xf270',
206
- "coffee" => '&#xf272',
207
- "compass" => '&#xf273',
208
- "compose" => '&#xf12c',
209
- "connection-bars" => '&#xf274',
210
- "contrast" => '&#xf275',
211
- "crop" => '&#xf3c1',
212
- "cube" => '&#xf318',
213
- "disc" => '&#xf12d',
214
- "document" => '&#xf12f',
215
- "document-text" => '&#xf12e',
216
- "drag" => '&#xf130',
217
- "earth" => '&#xf276',
218
- "easel" => '&#xf3c2',
219
- "edit" => '&#xf2bf',
220
- "egg" => '&#xf277',
221
- "eject" => '&#xf131',
222
- "email" => '&#xf132',
223
- "email-unread" => '&#xf3c3',
224
- "erlenmeyer-flask" => '&#xf3c5',
225
- "erlenmeyer-flask-bubbles" => '&#xf3c4',
226
- "eye" => '&#xf133',
227
- "eye-disabled" => '&#xf306',
228
- "female" => '&#xf278',
229
- "filing" => '&#xf134',
230
- "film-marker" => '&#xf135',
231
- "fireball" => '&#xf319',
232
- "flag" => '&#xf279',
233
- "flame" => '&#xf31a',
234
- "flash" => '&#xf137',
235
- "flash-off" => '&#xf136',
236
- "folder" => '&#xf139',
237
- "fork" => '&#xf27a',
238
- "fork-repo" => '&#xf2c0',
239
- "forward" => '&#xf13a',
240
- "funnel" => '&#xf31b',
241
- "gear-a" => '&#xf13d',
242
- "gear-b" => '&#xf13e',
243
- "grid" => '&#xf13f',
244
- "hammer" => '&#xf27b',
245
- "happy" => '&#xf31c',
246
- "happy-outline" => '&#xf3c6',
247
- "headphone" => '&#xf140',
248
- "heart" => '&#xf141',
249
- "heart-broken" => '&#xf31d',
250
- "help" => '&#xf143',
251
- "help-buoy" => '&#xf27c',
252
- "help-circled" => '&#xf142',
253
- "home" => '&#xf144',
254
- "icecream" => '&#xf27d',
255
- "image" => '&#xf147',
256
- "images" => '&#xf148',
257
- "information" => '&#xf14a',
258
- "information-circled" => '&#xf149',
259
- "ionic" => '&#xf14b',
260
- "ios-alarm" => '&#xf3c8',
261
- "ios-alarm-outline" => '&#xf3c7',
262
- "ios-albums" => '&#xf3ca',
263
- "ios-albums-outline" => '&#xf3c9',
264
- "ios-americanfootball" => '&#xf3cc',
265
- "ios-americanfootball-outline" => '&#xf3cb',
266
- "ios-analytics" => '&#xf3ce',
267
- "ios-analytics-outline" => '&#xf3cd',
268
- "ios-arrow-back" => '&#xf3cf',
269
- "ios-arrow-down" => '&#xf3d0',
270
- "ios-arrow-forward" => '&#xf3d1',
271
- "ios-arrow-left" => '&#xf3d2',
272
- "ios-arrow-right" => '&#xf3d3',
273
- "ios-arrow-thin-down" => '&#xf3d4',
274
- "ios-arrow-thin-left" => '&#xf3d5',
275
- "ios-arrow-thin-right" => '&#xf3d6',
276
- "ios-arrow-thin-up" => '&#xf3d7',
277
- "ios-arrow-up" => '&#xf3d8',
278
- "ios-at" => '&#xf3da',
279
- "ios-at-outline" => '&#xf3d9',
280
- "ios-barcode" => '&#xf3dc',
281
- "ios-barcode-outline" => '&#xf3db',
282
- "ios-baseball" => '&#xf3de',
283
- "ios-baseball-outline" => '&#xf3dd',
284
- "ios-basketball" => '&#xf3e0',
285
- "ios-basketball-outline" => '&#xf3df',
286
- "ios-bell" => '&#xf3e2',
287
- "ios-bell-outline" => '&#xf3e1',
288
- "ios-body" => '&#xf3e4',
289
- "ios-body-outline" => '&#xf3e3',
290
- "ios-bolt" => '&#xf3e6',
291
- "ios-bolt-outline" => '&#xf3e5',
292
- "ios-book" => '&#xf3e8',
293
- "ios-book-outline" => '&#xf3e7',
294
- "ios-bookmarks" => '&#xf3ea',
295
- "ios-bookmarks-outline" => '&#xf3e9',
296
- "ios-box" => '&#xf3ec',
297
- "ios-box-outline" => '&#xf3eb',
298
- "ios-briefcase" => '&#xf3ee',
299
- "ios-briefcase-outline" => '&#xf3ed',
300
- "ios-browsers" => '&#xf3f0',
301
- "ios-browsers-outline" => '&#xf3ef',
302
- "ios-calculator" => '&#xf3f2',
303
- "ios-calculator-outline" => '&#xf3f1',
304
- "ios-calendar" => '&#xf3f4',
305
- "ios-calendar-outline" => '&#xf3f3',
306
- "ios-camera" => '&#xf3f6',
307
- "ios-camera-outline" => '&#xf3f5',
308
- "ios-cart" => '&#xf3f8',
309
- "ios-cart-outline" => '&#xf3f7',
310
- "ios-chatboxes" => '&#xf3fa',
311
- "ios-chatboxes-outline" => '&#xf3f9',
312
- "ios-chatbubble" => '&#xf3fc',
313
- "ios-chatbubble-outline" => '&#xf3fb',
314
- "ios-checkmark" => '&#xf3ff',
315
- "ios-checkmark-empty" => '&#xf3fd',
316
- "ios-checkmark-outline" => '&#xf3fe',
317
- "ios-circle-filled" => '&#xf400',
318
- "ios-circle-outline" => '&#xf401',
319
- "ios-clock" => '&#xf403',
320
- "ios-clock-outline" => '&#xf402',
321
- "ios-close" => '&#xf406',
322
- "ios-close-empty" => '&#xf404',
323
- "ios-close-outline" => '&#xf405',
324
- "ios-cloud" => '&#xf40c',
325
- "ios-cloud-download" => '&#xf408',
326
- "ios-cloud-download-outline" => '&#xf407',
327
- "ios-cloud-outline" => '&#xf409',
328
- "ios-cloud-upload" => '&#xf40b',
329
- "ios-cloud-upload-outline" => '&#xf40a',
330
- "ios-cloudy" => '&#xf410',
331
- "ios-cloudy-night" => '&#xf40e',
332
- "ios-cloudy-night-outline" => '&#xf40d',
333
- "ios-cloudy-outline" => '&#xf40f',
334
- "ios-cog" => '&#xf412',
335
- "ios-cog-outline" => '&#xf411',
336
- "ios-color-filter" => '&#xf414',
337
- "ios-color-filter-outline" => '&#xf413',
338
- "ios-color-wand" => '&#xf416',
339
- "ios-color-wand-outline" => '&#xf415',
340
- "ios-compose" => '&#xf418',
341
- "ios-compose-outline" => '&#xf417',
342
- "ios-contact" => '&#xf41a',
343
- "ios-contact-outline" => '&#xf419',
344
- "ios-copy" => '&#xf41c',
345
- "ios-copy-outline" => '&#xf41b',
346
- "ios-crop" => '&#xf41e',
347
- "ios-crop-strong" => '&#xf41d',
348
- "ios-download" => '&#xf420',
349
- "ios-download-outline" => '&#xf41f',
350
- "ios-drag" => '&#xf421',
351
- "ios-email" => '&#xf423',
352
- "ios-email-outline" => '&#xf422',
353
- "ios-eye" => '&#xf425',
354
- "ios-eye-outline" => '&#xf424',
355
- "ios-fastforward" => '&#xf427',
356
- "ios-fastforward-outline" => '&#xf426',
357
- "ios-filing" => '&#xf429',
358
- "ios-filing-outline" => '&#xf428',
359
- "ios-film" => '&#xf42b',
360
- "ios-film-outline" => '&#xf42a',
361
- "ios-flag" => '&#xf42d',
362
- "ios-flag-outline" => '&#xf42c',
363
- "ios-flame" => '&#xf42f',
364
- "ios-flame-outline" => '&#xf42e',
365
- "ios-flask" => '&#xf431',
366
- "ios-flask-outline" => '&#xf430',
367
- "ios-flower" => '&#xf433',
368
- "ios-flower-outline" => '&#xf432',
369
- "ios-folder" => '&#xf435',
370
- "ios-folder-outline" => '&#xf434',
371
- "ios-football" => '&#xf437',
372
- "ios-football-outline" => '&#xf436',
373
- "ios-game-controller-a" => '&#xf439',
374
- "ios-game-controller-a-outline" => '&#xf438',
375
- "ios-game-controller-b" => '&#xf43b',
376
- "ios-game-controller-b-outline" => '&#xf43a',
377
- "ios-gear" => '&#xf43d',
378
- "ios-gear-outline" => '&#xf43c',
379
- "ios-glasses" => '&#xf43f',
380
- "ios-glasses-outline" => '&#xf43e',
381
- "ios-grid-view" => '&#xf441',
382
- "ios-grid-view-outline" => '&#xf440',
383
- "ios-heart" => '&#xf443',
384
- "ios-heart-outline" => '&#xf442',
385
- "ios-help" => '&#xf446',
386
- "ios-help-empty" => '&#xf444',
387
- "ios-help-outline" => '&#xf445',
388
- "ios-home" => '&#xf448',
389
- "ios-home-outline" => '&#xf447',
390
- "ios-infinite" => '&#xf44a',
391
- "ios-infinite-outline" => '&#xf449',
392
- "ios-information" => '&#xf44d',
393
- "ios-information-empty" => '&#xf44b',
394
- "ios-information-outline" => '&#xf44c',
395
- "ios-ionic-outline" => '&#xf44e',
396
- "ios-keypad" => '&#xf450',
397
- "ios-keypad-outline" => '&#xf44f',
398
- "ios-lightbulb" => '&#xf452',
399
- "ios-lightbulb-outline" => '&#xf451',
400
- "ios-list" => '&#xf454',
401
- "ios-list-outline" => '&#xf453',
402
- "ios-location" => '&#xf456',
403
- "ios-location-outline" => '&#xf455',
404
- "ios-locked" => '&#xf458',
405
- "ios-locked-outline" => '&#xf457',
406
- "ios-loop" => '&#xf45a',
407
- "ios-loop-strong" => '&#xf459',
408
- "ios-medical" => '&#xf45c',
409
- "ios-medical-outline" => '&#xf45b',
410
- "ios-medkit" => '&#xf45e',
411
- "ios-medkit-outline" => '&#xf45d',
412
- "ios-mic" => '&#xf461',
413
- "ios-mic-off" => '&#xf45f',
414
- "ios-mic-outline" => '&#xf460',
415
- "ios-minus" => '&#xf464',
416
- "ios-minus-empty" => '&#xf462',
417
- "ios-minus-outline" => '&#xf463',
418
- "ios-monitor" => '&#xf466',
419
- "ios-monitor-outline" => '&#xf465',
420
- "ios-moon" => '&#xf468',
421
- "ios-moon-outline" => '&#xf467',
422
- "ios-more" => '&#xf46a',
423
- "ios-more-outline" => '&#xf469',
424
- "ios-musical-note" => '&#xf46b',
425
- "ios-musical-notes" => '&#xf46c',
426
- "ios-navigate" => '&#xf46e',
427
- "ios-navigate-outline" => '&#xf46d',
428
- "ios-nutrition" => '&#xf470',
429
- "ios-nutrition-outline" => '&#xf46f',
430
- "ios-paper" => '&#xf472',
431
- "ios-paper-outline" => '&#xf471',
432
- "ios-paperplane" => '&#xf474',
433
- "ios-paperplane-outline" => '&#xf473',
434
- "ios-partlysunny" => '&#xf476',
435
- "ios-partlysunny-outline" => '&#xf475',
436
- "ios-pause" => '&#xf478',
437
- "ios-pause-outline" => '&#xf477',
438
- "ios-paw" => '&#xf47a',
439
- "ios-paw-outline" => '&#xf479',
440
- "ios-people" => '&#xf47c',
441
- "ios-people-outline" => '&#xf47b',
442
- "ios-person" => '&#xf47e',
443
- "ios-person-outline" => '&#xf47d',
444
- "ios-personadd" => '&#xf480',
445
- "ios-personadd-outline" => '&#xf47f',
446
- "ios-photos" => '&#xf482',
447
- "ios-photos-outline" => '&#xf481',
448
- "ios-pie" => '&#xf484',
449
- "ios-pie-outline" => '&#xf483',
450
- "ios-pint" => '&#xf486',
451
- "ios-pint-outline" => '&#xf485',
452
- "ios-play" => '&#xf488',
453
- "ios-play-outline" => '&#xf487',
454
- "ios-plus" => '&#xf48b',
455
- "ios-plus-empty" => '&#xf489',
456
- "ios-plus-outline" => '&#xf48a',
457
- "ios-pricetag" => '&#xf48d',
458
- "ios-pricetag-outline" => '&#xf48c',
459
- "ios-pricetags" => '&#xf48f',
460
- "ios-pricetags-outline" => '&#xf48e',
461
- "ios-printer" => '&#xf491',
462
- "ios-printer-outline" => '&#xf490',
463
- "ios-pulse" => '&#xf493',
464
- "ios-pulse-strong" => '&#xf492',
465
- "ios-rainy" => '&#xf495',
466
- "ios-rainy-outline" => '&#xf494',
467
- "ios-recording" => '&#xf497',
468
- "ios-recording-outline" => '&#xf496',
469
- "ios-redo" => '&#xf499',
470
- "ios-redo-outline" => '&#xf498',
471
- "ios-refresh" => '&#xf49c',
472
- "ios-refresh-empty" => '&#xf49a',
473
- "ios-refresh-outline" => '&#xf49b',
474
- "ios-reload" => '&#xf49d',
475
- "ios-reverse-camera" => '&#xf49f',
476
- "ios-reverse-camera-outline" => '&#xf49e',
477
- "ios-rewind" => '&#xf4a1',
478
- "ios-rewind-outline" => '&#xf4a0',
479
- "ios-rose" => '&#xf4a3',
480
- "ios-rose-outline" => '&#xf4a2',
481
- "ios-search" => '&#xf4a5',
482
- "ios-search-strong" => '&#xf4a4',
483
- "ios-settings" => '&#xf4a7',
484
- "ios-settings-strong" => '&#xf4a6',
485
- "ios-shuffle" => '&#xf4a9',
486
- "ios-shuffle-strong" => '&#xf4a8',
487
- "ios-skipbackward" => '&#xf4ab',
488
- "ios-skipbackward-outline" => '&#xf4aa',
489
- "ios-skipforward" => '&#xf4ad',
490
- "ios-skipforward-outline" => '&#xf4ac',
491
- "ios-snowy" => '&#xf4ae',
492
- "ios-speedometer" => '&#xf4b0',
493
- "ios-speedometer-outline" => '&#xf4af',
494
- "ios-star" => '&#xf4b3',
495
- "ios-star-half" => '&#xf4b1',
496
- "ios-star-outline" => '&#xf4b2',
497
- "ios-stopwatch" => '&#xf4b5',
498
- "ios-stopwatch-outline" => '&#xf4b4',
499
- "ios-sunny" => '&#xf4b7',
500
- "ios-sunny-outline" => '&#xf4b6',
501
- "ios-telephone" => '&#xf4b9',
502
- "ios-telephone-outline" => '&#xf4b8',
503
- "ios-tennisball" => '&#xf4bb',
504
- "ios-tennisball-outline" => '&#xf4ba',
505
- "ios-thunderstorm" => '&#xf4bd',
506
- "ios-thunderstorm-outline" => '&#xf4bc',
507
- "ios-time" => '&#xf4bf',
508
- "ios-time-outline" => '&#xf4be',
509
- "ios-timer" => '&#xf4c1',
510
- "ios-timer-outline" => '&#xf4c0',
511
- "ios-toggle" => '&#xf4c3',
512
- "ios-toggle-outline" => '&#xf4c2',
513
- "ios-trash" => '&#xf4c5',
514
- "ios-trash-outline" => '&#xf4c4',
515
- "ios-undo" => '&#xf4c7',
516
- "ios-undo-outline" => '&#xf4c6',
517
- "ios-unlocked" => '&#xf4c9',
518
- "ios-unlocked-outline" => '&#xf4c8',
519
- "ios-upload" => '&#xf4cb',
520
- "ios-upload-outline" => '&#xf4ca',
521
- "ios-videocam" => '&#xf4cd',
522
- "ios-videocam-outline" => '&#xf4cc',
523
- "ios-volume-high" => '&#xf4ce',
524
- "ios-volume-low" => '&#xf4cf',
525
- "ios-wineglass" => '&#xf4d1',
526
- "ios-wineglass-outline" => '&#xf4d0',
527
- "ios-world" => '&#xf4d3',
528
- "ios-world-outline" => '&#xf4d2',
529
- "ipad" => '&#xf1f9',
530
- "iphone" => '&#xf1fa',
531
- "ipod" => '&#xf1fb',
532
- "jet" => '&#xf295',
533
- "key" => '&#xf296',
534
- "knife" => '&#xf297',
535
- "laptop" => '&#xf1fc',
536
- "leaf" => '&#xf1fd',
537
- "levels" => '&#xf298',
538
- "lightbulb" => '&#xf299',
539
- "link" => '&#xf1fe',
540
- "load-a" => '&#xf29a',
541
- "load-b" => '&#xf29b',
542
- "load-c" => '&#xf29c',
543
- "load-d" => '&#xf29d',
544
- "location" => '&#xf1ff',
545
- "lock-combination" => '&#xf4d4',
546
- "locked" => '&#xf200',
547
- "log-in" => '&#xf29e',
548
- "log-out" => '&#xf29f',
549
- "loop" => '&#xf201',
550
- "magnet" => '&#xf2a0',
551
- "male" => '&#xf2a1',
552
- "man" => '&#xf202',
553
- "map" => '&#xf203',
554
- "medkit" => '&#xf2a2',
555
- "merge" => '&#xf33f',
556
- "mic-a" => '&#xf204',
557
- "mic-b" => '&#xf205',
558
- "mic-c" => '&#xf206',
559
- "minus" => '&#xf209',
560
- "minus-circled" => '&#xf207',
561
- "minus-round" => '&#xf208',
562
- "model-s" => '&#xf2c1',
563
- "monitor" => '&#xf20a',
564
- "more" => '&#xf20b',
565
- "mouse" => '&#xf340',
566
- "music-note" => '&#xf20c',
567
- "navicon" => '&#xf20e',
568
- "navicon-round" => '&#xf20d',
569
- "navigate" => '&#xf2a3',
570
- "network" => '&#xf341',
571
- "no-smoking" => '&#xf2c2',
572
- "nuclear" => '&#xf2a4',
573
- "outlet" => '&#xf342',
574
- "paintbrush" => '&#xf4d5',
575
- "paintbucket" => '&#xf4d6',
576
- "paper-airplane" => '&#xf2c3',
577
- "paperclip" => '&#xf20f',
578
- "pause" => '&#xf210',
579
- "person" => '&#xf213',
580
- "person-add" => '&#xf211',
581
- "person-stalker" => '&#xf212',
582
- "pie-graph" => '&#xf2a5',
583
- "pin" => '&#xf2a6',
584
- "pinpoint" => '&#xf2a7',
585
- "pizza" => '&#xf2a8',
586
- "plane" => '&#xf214',
587
- "planet" => '&#xf343',
588
- "play" => '&#xf215',
589
- "playstation" => '&#xf30a',
590
- "plus" => '&#xf218',
591
- "plus-circled" => '&#xf216',
592
- "plus-round" => '&#xf217',
593
- "podium" => '&#xf344',
594
- "pound" => '&#xf219',
595
- "power" => '&#xf2a9',
596
- "pricetag" => '&#xf2aa',
597
- "pricetags" => '&#xf2ab',
598
- "printer" => '&#xf21a',
599
- "pull-request" => '&#xf345',
600
- "qr-scanner" => '&#xf346',
601
- "quote" => '&#xf347',
602
- "radio-waves" => '&#xf2ac',
603
- "record" => '&#xf21b',
604
- "refresh" => '&#xf21c',
605
- "reply" => '&#xf21e',
606
- "reply-all" => '&#xf21d',
607
- "ribbon-a" => '&#xf348',
608
- "ribbon-b" => '&#xf349',
609
- "sad" => '&#xf34a',
610
- "sad-outline" => '&#xf4d7',
611
- "scissors" => '&#xf34b',
612
- "search" => '&#xf21f',
613
- "settings" => '&#xf2ad',
614
- "share" => '&#xf220',
615
- "shuffle" => '&#xf221',
616
- "skip-backward" => '&#xf222',
617
- "skip-forward" => '&#xf223',
618
- "social-android" => '&#xf225',
619
- "social-android-outline" => '&#xf224',
620
- "social-angular" => '&#xf4d9',
621
- "social-angular-outline" => '&#xf4d8',
622
- "social-apple" => '&#xf227',
623
- "social-apple-outline" => '&#xf226',
624
- "social-bitcoin" => '&#xf2af',
625
- "social-bitcoin-outline" => '&#xf2ae',
626
- "social-buffer" => '&#xf229',
627
- "social-buffer-outline" => '&#xf228',
628
- "social-chrome" => '&#xf4db',
629
- "social-chrome-outline" => '&#xf4da',
630
- "social-codepen" => '&#xf4dd',
631
- "social-codepen-outline" => '&#xf4dc',
632
- "social-css3" => '&#xf4df',
633
- "social-css3-outline" => '&#xf4de',
634
- "social-designernews" => '&#xf22b',
635
- "social-designernews-outline" => '&#xf22a',
636
- "social-dribbble" => '&#xf22d',
637
- "social-dribbble-outline" => '&#xf22c',
638
- "social-dropbox" => '&#xf22f',
639
- "social-dropbox-outline" => '&#xf22e',
640
- "social-euro" => '&#xf4e1',
641
- "social-euro-outline" => '&#xf4e0',
642
- "social-facebook" => '&#xf231',
643
- "social-facebook-outline" => '&#xf230',
644
- "social-foursquare" => '&#xf34d',
645
- "social-foursquare-outline" => '&#xf34c',
646
- "social-freebsd-devil" => '&#xf2c4',
647
- "social-github" => '&#xf233',
648
- "social-github-outline" => '&#xf232',
649
- "social-google" => '&#xf34f',
650
- "social-google-outline" => '&#xf34e',
651
- "social-googleplus" => '&#xf235',
652
- "social-googleplus-outline" => '&#xf234',
653
- "social-hackernews" => '&#xf237',
654
- "social-hackernews-outline" => '&#xf236',
655
- "social-html5" => '&#xf4e3',
656
- "social-html5-outline" => '&#xf4e2',
657
- "social-instagram" => '&#xf351',
658
- "social-instagram-outline" => '&#xf350',
659
- "social-javascript" => '&#xf4e5',
660
- "social-javascript-outline" => '&#xf4e4',
661
- "social-linkedin" => '&#xf239',
662
- "social-linkedin-outline" => '&#xf238',
663
- "social-markdown" => '&#xf4e6',
664
- "social-nodejs" => '&#xf4e7',
665
- "social-octocat" => '&#xf4e8',
666
- "social-pinterest" => '&#xf2b1',
667
- "social-pinterest-outline" => '&#xf2b0',
668
- "social-python" => '&#xf4e9',
669
- "social-reddit" => '&#xf23b',
670
- "social-reddit-outline" => '&#xf23a',
671
- "social-rss" => '&#xf23d',
672
- "social-rss-outline" => '&#xf23c',
673
- "social-sass" => '&#xf4ea',
674
- "social-skype" => '&#xf23f',
675
- "social-skype-outline" => '&#xf23e',
676
- "social-snapchat" => '&#xf4ec',
677
- "social-snapchat-outline" => '&#xf4eb',
678
- "social-tumblr" => '&#xf241',
679
- "social-tumblr-outline" => '&#xf240',
680
- "social-tux" => '&#xf2c5',
681
- "social-twitch" => '&#xf4ee',
682
- "social-twitch-outline" => '&#xf4ed',
683
- "social-twitter" => '&#xf243',
684
- "social-twitter-outline" => '&#xf242',
685
- "social-usd" => '&#xf353',
686
- "social-usd-outline" => '&#xf352',
687
- "social-vimeo" => '&#xf245',
688
- "social-vimeo-outline" => '&#xf244',
689
- "social-whatsapp" => '&#xf4f0',
690
- "social-whatsapp-outline" => '&#xf4ef',
691
- "social-windows" => '&#xf247',
692
- "social-windows-outline" => '&#xf246',
693
- "social-wordpress" => '&#xf249',
694
- "social-wordpress-outline" => '&#xf248',
695
- "social-yahoo" => '&#xf24b',
696
- "social-yahoo-outline" => '&#xf24a',
697
- "social-yen" => '&#xf4f2',
698
- "social-yen-outline" => '&#xf4f1',
699
- "social-youtube" => '&#xf24d',
700
- "social-youtube-outline" => '&#xf24c',
701
- "soup-can" => '&#xf4f4',
702
- "soup-can-outline" => '&#xf4f3',
703
- "speakerphone" => '&#xf2b2',
704
- "speedometer" => '&#xf2b3',
705
- "spoon" => '&#xf2b4',
706
- "star" => '&#xf24e',
707
- "stats-bars" => '&#xf2b5',
708
- "steam" => '&#xf30b',
709
- "stop" => '&#xf24f',
710
- "thermometer" => '&#xf2b6',
711
- "thumbsdown" => '&#xf250',
712
- "thumbsup" => '&#xf251',
713
- "toggle" => '&#xf355',
714
- "toggle-filled" => '&#xf354',
715
- "transgender" => '&#xf4f5',
716
- "trash-a" => '&#xf252',
717
- "trash-b" => '&#xf253',
718
- "trophy" => '&#xf356',
719
- "tshirt" => '&#xf4f7',
720
- "tshirt-outline" => '&#xf4f6',
721
- "umbrella" => '&#xf2b7',
722
- "university" => '&#xf357',
723
- "unlocked" => '&#xf254',
724
- "upload" => '&#xf255',
725
- "usb" => '&#xf2b8',
726
- "videocamera" => '&#xf256',
727
- "volume-high" => '&#xf257',
728
- "volume-low" => '&#xf258',
729
- "volume-medium" => '&#xf259',
730
- "volume-mute" => '&#xf25a',
731
- "wand" => '&#xf358',
732
- "waterdrop" => '&#xf25b',
733
- "wifi" => '&#xf25c',
734
- "wineglass" => '&#xf2b9',
735
- "woman" => '&#xf25d',
736
- "wrench" => '&#xf2ba',
737
- "xbox" => '&#xf30c',
738
- ));
739
- }
740
- add_filter('siteorigin_widgets_icons_ionicons', 'siteorigin_widgets_icons_ionicons_filter');
1
+ <?php
2
+
3
+ function siteorigin_widgets_icons_ionicons_filter( $icons ){
4
+ return array_merge($icons, array(
5
+ "alert" => '&#xf101;',
6
+ "alert-circled" => '&#xf100;',
7
+ "android-add" => '&#xf2c7;',
8
+ "android-add-circle" => '&#xf359;',
9
+ "android-alarm-clock" => '&#xf35a;',
10
+ "android-alert" => '&#xf35b;',
11
+ "android-apps" => '&#xf35c;',
12
+ "android-archive" => '&#xf2c9;',
13
+ "android-arrow-back" => '&#xf2ca;',
14
+ "android-arrow-down" => '&#xf35d;',
15
+ "android-arrow-dropdown" => '&#xf35f;',
16
+ "android-arrow-dropdown-circle" => '&#xf35e;',
17
+ "android-arrow-dropleft" => '&#xf361;',
18
+ "android-arrow-dropleft-circle" => '&#xf360;',
19
+ "android-arrow-dropright" => '&#xf363;',
20
+ "android-arrow-dropright-circle" => '&#xf362;',
21
+ "android-arrow-dropup" => '&#xf365;',
22
+ "android-arrow-dropup-circle" => '&#xf364;',
23
+ "android-arrow-forward" => '&#xf30f;',
24
+ "android-arrow-up" => '&#xf366;',
25
+ "android-attach" => '&#xf367;',
26
+ "android-bar" => '&#xf368;',
27
+ "android-bicycle" => '&#xf369;',
28
+ "android-boat" => '&#xf36a;',
29
+ "android-bookmark" => '&#xf36b;',
30
+ "android-bulb" => '&#xf36c;',
31
+ "android-bus" => '&#xf36d;',
32
+ "android-calendar" => '&#xf2d1;',
33
+ "android-call" => '&#xf2d2;',
34
+ "android-camera" => '&#xf2d3;',
35
+ "android-cancel" => '&#xf36e;',
36
+ "android-car" => '&#xf36f;',
37
+ "android-cart" => '&#xf370;',
38
+ "android-chat" => '&#xf2d4;',
39
+ "android-checkbox" => '&#xf374;',
40
+ "android-checkbox-blank" => '&#xf371;',
41
+ "android-checkbox-outline" => '&#xf373;',
42
+ "android-checkbox-outline-blank" => '&#xf372;',
43
+ "android-checkmark-circle" => '&#xf375;',
44
+ "android-clipboard" => '&#xf376;',
45
+ "android-close" => '&#xf2d7;',
46
+ "android-cloud" => '&#xf37a;',
47
+ "android-cloud-circle" => '&#xf377;',
48
+ "android-cloud-done" => '&#xf378;',
49
+ "android-cloud-outline" => '&#xf379;',
50
+ "android-color-palette" => '&#xf37b;',
51
+ "android-compass" => '&#xf37c;',
52
+ "android-contact" => '&#xf2d8;',
53
+ "android-contacts" => '&#xf2d9;',
54
+ "android-contract" => '&#xf37d;',
55
+ "android-create" => '&#xf37e;',
56
+ "android-delete" => '&#xf37f;',
57
+ "android-desktop" => '&#xf380;',
58
+ "android-document" => '&#xf381;',
59
+ "android-done" => '&#xf383;',
60
+ "android-done-all" => '&#xf382;',
61
+ "android-download" => '&#xf2dd;',
62
+ "android-drafts" => '&#xf384;',
63
+ "android-exit" => '&#xf385;',
64
+ "android-expand" => '&#xf386;',
65
+ "android-favorite" => '&#xf388;',
66
+ "android-favorite-outline" => '&#xf387;',
67
+ "android-film" => '&#xf389;',
68
+ "android-folder" => '&#xf2e0;',
69
+ "android-folder-open" => '&#xf38a;',
70
+ "android-funnel" => '&#xf38b;',
71
+ "android-globe" => '&#xf38c;',
72
+ "android-hand" => '&#xf2e3;',
73
+ "android-hangout" => '&#xf38d;',
74
+ "android-happy" => '&#xf38e;',
75
+ "android-home" => '&#xf38f;',
76
+ "android-image" => '&#xf2e4;',
77
+ "android-laptop" => '&#xf390;',
78
+ "android-list" => '&#xf391;',
79
+ "android-locate" => '&#xf2e9;',
80
+ "android-lock" => '&#xf392;',
81
+ "android-mail" => '&#xf2eb;',
82
+ "android-map" => '&#xf393;',
83
+ "android-menu" => '&#xf394;',
84
+ "android-microphone" => '&#xf2ec;',
85
+ "android-microphone-off" => '&#xf395;',
86
+ "android-more-horizontal" => '&#xf396;',
87
+ "android-more-vertical" => '&#xf397;',
88
+ "android-navigate" => '&#xf398;',
89
+ "android-notifications" => '&#xf39b;',
90
+ "android-notifications-none" => '&#xf399;',
91
+ "android-notifications-off" => '&#xf39a;',
92
+ "android-open" => '&#xf39c;',
93
+ "android-options" => '&#xf39d;',
94
+ "android-people" => '&#xf39e;',
95
+ "android-person" => '&#xf3a0;',
96
+ "android-person-add" => '&#xf39f;',
97
+ "android-phone-landscape" => '&#xf3a1;',
98
+ "android-phone-portrait" => '&#xf3a2;',
99
+ "android-pin" => '&#xf3a3;',
100
+ "android-plane" => '&#xf3a4;',
101
+ "android-playstore" => '&#xf2f0;',
102
+ "android-print" => '&#xf3a5;',
103
+ "android-radio-button-off" => '&#xf3a6;',
104
+ "android-radio-button-on" => '&#xf3a7;',
105
+ "android-refresh" => '&#xf3a8;',
106
+ "android-remove" => '&#xf2f4;',
107
+ "android-remove-circle" => '&#xf3a9;',
108
+ "android-restaurant" => '&#xf3aa;',
109
+ "android-sad" => '&#xf3ab;',
110
+ "android-search" => '&#xf2f5;',
111
+ "android-send" => '&#xf2f6;',
112
+ "android-settings" => '&#xf2f7;',
113
+ "android-share" => '&#xf2f8;',
114
+ "android-share-alt" => '&#xf3ac;',
115
+ "android-star" => '&#xf2fc;',
116
+ "android-star-half" => '&#xf3ad;',
117
+ "android-star-outline" => '&#xf3ae;',
118
+ "android-stopwatch" => '&#xf2fd;',
119
+ "android-subway" => '&#xf3af;',
120
+ "android-sunny" => '&#xf3b0;',
121
+ "android-sync" => '&#xf3b1;',
122
+ "android-textsms" => '&#xf3b2;',
123
+ "android-time" => '&#xf3b3;',
124
+ "android-train" => '&#xf3b4;',
125
+ "android-unlock" => '&#xf3b5;',
126
+ "android-upload" => '&#xf3b6;',
127
+ "android-volume-down" => '&#xf3b7;',
128
+ "android-volume-mute" => '&#xf3b8;',
129
+ "android-volume-off" => '&#xf3b9;',
130
+ "android-volume-up" => '&#xf3ba;',
131
+ "android-walk" => '&#xf3bb;',
132
+ "android-warning" => '&#xf3bc;',
133
+ "android-watch" => '&#xf3bd;',
134
+ "android-wifi" => '&#xf305;',
135
+ "aperture" => '&#xf313;',
136
+ "archive" => '&#xf102;',
137
+ "arrow-down-a" => '&#xf103;',
138
+ "arrow-down-b" => '&#xf104;',
139
+ "arrow-down-c" => '&#xf105;',
140
+ "arrow-expand" => '&#xf25e;',
141
+ "arrow-graph-down-left" => '&#xf25f;',
142
+ "arrow-graph-down-right" => '&#xf260;',
143
+ "arrow-graph-up-left" => '&#xf261;',
144
+ "arrow-graph-up-right" => '&#xf262;',
145
+ "arrow-left-a" => '&#xf106;',
146
+ "arrow-left-b" => '&#xf107;',
147
+ "arrow-left-c" => '&#xf108;',
148
+ "arrow-move" => '&#xf263;',
149
+ "arrow-resize" => '&#xf264;',
150
+ "arrow-return-left" => '&#xf265;',
151
+ "arrow-return-right" => '&#xf266;',
152
+ "arrow-right-a" => '&#xf109;',
153
+ "arrow-right-b" => '&#xf10a;',
154
+ "arrow-right-c" => '&#xf10b;',
155
+ "arrow-shrink" => '&#xf267;',
156
+ "arrow-swap" => '&#xf268;',
157
+ "arrow-up-a" => '&#xf10c;',
158
+ "arrow-up-b" => '&#xf10d;',
159
+ "arrow-up-c" => '&#xf10e;',
160
+ "asterisk" => '&#xf314;',
161
+ "at" => '&#xf10f;',
162
+ "backspace" => '&#xf3bf;',
163
+ "backspace-outline" => '&#xf3be;',
164
+ "bag" => '&#xf110;',
165
+ "battery-charging" => '&#xf111;',
166
+ "battery-empty" => '&#xf112;',
167
+ "battery-full" => '&#xf113;',
168
+ "battery-half" => '&#xf114;',
169
+ "battery-low" => '&#xf115;',
170
+ "beaker" => '&#xf269;',
171
+ "beer" => '&#xf26a;',
172
+ "bluetooth" => '&#xf116;',
173
+ "bonfire" => '&#xf315;',
174
+ "bookmark" => '&#xf26b;',
175
+ "bowtie" => '&#xf3c0;',
176
+ "briefcase" => '&#xf26c;',
177
+ "bug" => '&#xf2be;',
178
+ "calculator" => '&#xf26d;',
179
+ "calendar" => '&#xf117;',
180
+ "camera" => '&#xf118;',
181
+ "card" => '&#xf119;',
182
+ "cash" => '&#xf316;',
183
+ "chatbox" => '&#xf11b;',
184
+ "chatbox-working" => '&#xf11a;',
185
+ "chatboxes" => '&#xf11c;',
186
+ "chatbubble" => '&#xf11e;',
187
+ "chatbubble-working" => '&#xf11d;',
188
+ "chatbubbles" => '&#xf11f;',
189
+ "checkmark" => '&#xf122;',
190
+ "checkmark-circled" => '&#xf120;',
191
+ "checkmark-round" => '&#xf121;',
192
+ "chevron-down" => '&#xf123;',
193
+ "chevron-left" => '&#xf124;',
194
+ "chevron-right" => '&#xf125;',
195
+ "chevron-up" => '&#xf126;',
196
+ "clipboard" => '&#xf127;',
197
+ "clock" => '&#xf26e;',
198
+ "close" => '&#xf12a;',
199
+ "close-circled" => '&#xf128;',
200
+ "close-round" => '&#xf129;',
201
+ "closed-captioning" => '&#xf317;',
202
+ "cloud" => '&#xf12b;',
203
+ "code" => '&#xf271;',
204
+ "code-download" => '&#xf26f;',
205
+ "code-working" => '&#xf270;',
206
+ "coffee" => '&#xf272;',
207
+ "compass" => '&#xf273;',
208
+ "compose" => '&#xf12c;',
209
+ "connection-bars" => '&#xf274;',
210
+ "contrast" => '&#xf275;',
211
+ "crop" => '&#xf3c1;',
212
+ "cube" => '&#xf318;',
213
+ "disc" => '&#xf12d;',
214
+ "document" => '&#xf12f;',
215
+ "document-text" => '&#xf12e;',
216
+ "drag" => '&#xf130;',
217
+ "earth" => '&#xf276;',
218
+ "easel" => '&#xf3c2;',
219
+ "edit" => '&#xf2bf;',
220
+ "egg" => '&#xf277;',
221
+ "eject" => '&#xf131;',
222
+ "email" => '&#xf132;',
223
+ "email-unread" => '&#xf3c3;',
224
+ "erlenmeyer-flask" => '&#xf3c5;',
225
+ "erlenmeyer-flask-bubbles" => '&#xf3c4;',
226
+ "eye" => '&#xf133;',
227
+ "eye-disabled" => '&#xf306;',
228
+ "female" => '&#xf278;',
229
+ "filing" => '&#xf134;',
230
+ "film-marker" => '&#xf135;',
231
+ "fireball" => '&#xf319;',
232
+ "flag" => '&#xf279;',
233
+ "flame" => '&#xf31a;',
234
+ "flash" => '&#xf137;',
235
+ "flash-off" => '&#xf136;',
236
+ "folder" => '&#xf139;',
237
+ "fork" => '&#xf27a;',
238
+ "fork-repo" => '&#xf2c0;',
239
+ "forward" => '&#xf13a;',
240
+ "funnel" => '&#xf31b;',
241
+ "gear-a" => '&#xf13d;',
242
+ "gear-b" => '&#xf13e;',
243
+ "grid" => '&#xf13f;',
244
+ "hammer" => '&#xf27b;',
245
+ "happy" => '&#xf31c;',
246
+ "happy-outline" => '&#xf3c6;',
247
+ "headphone" => '&#xf140;',
248
+ "heart" => '&#xf141;',
249
+ "heart-broken" => '&#xf31d;',
250
+ "help" => '&#xf143;',
251
+ "help-buoy" => '&#xf27c;',
252
+ "help-circled" => '&#xf142;',
253
+ "home" => '&#xf144;',
254
+ "icecream" => '&#xf27d;',
255
+ "image" => '&#xf147;',
256
+ "images" => '&#xf148;',
257
+ "information" => '&#xf14a;',
258
+ "information-circled" => '&#xf149;',
259
+ "ionic" => '&#xf14b;',
260
+ "ios-alarm" => '&#xf3c8;',
261
+ "ios-alarm-outline" => '&#xf3c7;',
262
+ "ios-albums" => '&#xf3ca;',
263
+ "ios-albums-outline" => '&#xf3c9;',
264
+ "ios-americanfootball" => '&#xf3cc;',
265
+ "ios-americanfootball-outline" => '&#xf3cb;',
266
+ "ios-analytics" => '&#xf3ce;',
267
+ "ios-analytics-outline" => '&#xf3cd;',
268
+ "ios-arrow-back" => '&#xf3cf;',
269
+ "ios-arrow-down" => '&#xf3d0;',
270
+ "ios-arrow-forward" => '&#xf3d1;',
271
+ "ios-arrow-left" => '&#xf3d2;',
272
+ "ios-arrow-right" => '&#xf3d3;',
273
+ "ios-arrow-thin-down" => '&#xf3d4;',
274
+ "ios-arrow-thin-left" => '&#xf3d5;',
275
+ "ios-arrow-thin-right" => '&#xf3d6;',
276
+ "ios-arrow-thin-up" => '&#xf3d7;',
277
+ "ios-arrow-up" => '&#xf3d8;',
278
+ "ios-at" => '&#xf3da;',
279
+ "ios-at-outline" => '&#xf3d9;',
280
+ "ios-barcode" => '&#xf3dc;',
281
+ "ios-barcode-outline" => '&#xf3db;',
282
+ "ios-baseball" => '&#xf3de;',
283
+ "ios-baseball-outline" => '&#xf3dd;',
284
+ "ios-basketball" => '&#xf3e0;',
285
+ "ios-basketball-outline" => '&#xf3df;',
286
+ "ios-bell" => '&#xf3e2;',
287
+ "ios-bell-outline" => '&#xf3e1;',
288
+ "ios-body" => '&#xf3e4;',
289
+ "ios-body-outline" => '&#xf3e3;',
290
+ "ios-bolt" => '&#xf3e6;',
291
+ "ios-bolt-outline" => '&#xf3e5;',
292
+ "ios-book" => '&#xf3e8;',
293
+ "ios-book-outline" => '&#xf3e7;',
294
+ "ios-bookmarks" => '&#xf3ea;',
295
+ "ios-bookmarks-outline" => '&#xf3e9;',
296
+ "ios-box" => '&#xf3ec;',
297
+ "ios-box-outline" => '&#xf3eb;',
298
+ "ios-briefcase" => '&#xf3ee;',
299
+ "ios-briefcase-outline" => '&#xf3ed;',
300
+ "ios-browsers" => '&#xf3f0;',
301
+ "ios-browsers-outline" => '&#xf3ef;',
302
+ "ios-calculator" => '&#xf3f2;',
303
+ "ios-calculator-outline" => '&#xf3f1;',
304
+ "ios-calendar" => '&#xf3f4;',
305
+ "ios-calendar-outline" => '&#xf3f3;',
306
+ "ios-camera" => '&#xf3f6;',
307
+ "ios-camera-outline" => '&#xf3f5;',
308
+ "ios-cart" => '&#xf3f8;',
309
+ "ios-cart-outline" => '&#xf3f7;',
310
+ "ios-chatboxes" => '&#xf3fa;',
311
+ "ios-chatboxes-outline" => '&#xf3f9;',
312
+ "ios-chatbubble" => '&#xf3fc;',
313
+ "ios-chatbubble-outline" => '&#xf3fb;',
314
+ "ios-checkmark" => '&#xf3ff;',
315
+ "ios-checkmark-empty" => '&#xf3fd;',
316
+ "ios-checkmark-outline" => '&#xf3fe;',
317
+ "ios-circle-filled" => '&#xf400;',
318
+ "ios-circle-outline" => '&#xf401;',
319
+ "ios-clock" => '&#xf403;',
320
+ "ios-clock-outline" => '&#xf402;',
321
+ "ios-close" => '&#xf406;',
322
+ "ios-close-empty" => '&#xf404;',
323
+ "ios-close-outline" => '&#xf405;',
324
+ "ios-cloud" => '&#xf40c;',
325
+ "ios-cloud-download" => '&#xf408;',
326
+ "ios-cloud-download-outline" => '&#xf407;',
327
+ "ios-cloud-outline" => '&#xf409;',
328
+ "ios-cloud-upload" => '&#xf40b;',
329
+ "ios-cloud-upload-outline" => '&#xf40a;',
330
+ "ios-cloudy" => '&#xf410;',
331
+ "ios-cloudy-night" => '&#xf40e;',
332
+ "ios-cloudy-night-outline" => '&#xf40d;',
333
+ "ios-cloudy-outline" => '&#xf40f;',
334
+ "ios-cog" => '&#xf412;',
335
+ "ios-cog-outline" => '&#xf411;',
336
+ "ios-color-filter" => '&#xf414;',
337
+ "ios-color-filter-outline" => '&#xf413;',
338
+ "ios-color-wand" => '&#xf416;',
339
+ "ios-color-wand-outline" => '&#xf415;',
340
+ "ios-compose" => '&#xf418;',
341
+ "ios-compose-outline" => '&#xf417;',
342
+ "ios-contact" => '&#xf41a;',
343
+ "ios-contact-outline" => '&#xf419;',
344
+ "ios-copy" => '&#xf41c;',
345
+ "ios-copy-outline" => '&#xf41b;',
346
+ "ios-crop" => '&#xf41e;',
347
+ "ios-crop-strong" => '&#xf41d;',
348
+ "ios-download" => '&#xf420;',
349
+ "ios-download-outline" => '&#xf41f;',
350
+ "ios-drag" => '&#xf421;',
351
+ "ios-email" => '&#xf423;',
352
+ "ios-email-outline" => '&#xf422;',
353
+ "ios-eye" => '&#xf425;',
354
+ "ios-eye-outline" => '&#xf424;',
355
+ "ios-fastforward" => '&#xf427;',
356
+ "ios-fastforward-outline" => '&#xf426;',
357
+ "ios-filing" => '&#xf429;',
358
+ "ios-filing-outline" => '&#xf428;',
359
+ "ios-film" => '&#xf42b;',
360
+ "ios-film-outline" => '&#xf42a;',
361
+ "ios-flag" => '&#xf42d;',
362
+ "ios-flag-outline" => '&#xf42c;',
363
+ "ios-flame" => '&#xf42f;',
364
+ "ios-flame-outline" => '&#xf42e;',
365
+ "ios-flask" => '&#xf431;',
366
+ "ios-flask-outline" => '&#xf430;',
367
+ "ios-flower" => '&#xf433;',
368
+ "ios-flower-outline" => '&#xf432;',
369
+ "ios-folder" => '&#xf435;',
370
+ "ios-folder-outline" => '&#xf434;',
371
+ "ios-football" => '&#xf437;',
372
+ "ios-football-outline" => '&#xf436;',
373
+ "ios-game-controller-a" => '&#xf439;',
374
+ "ios-game-controller-a-outline" => '&#xf438;',
375
+ "ios-game-controller-b" => '&#xf43b;',
376
+ "ios-game-controller-b-outline" => '&#xf43a;',
377
+ "ios-gear" => '&#xf43d;',
378
+ "ios-gear-outline" => '&#xf43c;',
379
+ "ios-glasses" => '&#xf43f;',
380
+ "ios-glasses-outline" => '&#xf43e;',
381
+ "ios-grid-view" => '&#xf441;',
382
+ "ios-grid-view-outline" => '&#xf440;',
383
+ "ios-heart" => '&#xf443;',
384
+ "ios-heart-outline" => '&#xf442;',
385
+ "ios-help" => '&#xf446;',
386
+ "ios-help-empty" => '&#xf444;',
387
+ "ios-help-outline" => '&#xf445;',
388
+ "ios-home" => '&#xf448;',
389
+ "ios-home-outline" => '&#xf447;',
390
+ "ios-infinite" => '&#xf44a;',
391
+ "ios-infinite-outline" => '&#xf449;',
392
+ "ios-information" => '&#xf44d;',
393
+ "ios-information-empty" => '&#xf44b;',
394
+ "ios-information-outline" => '&#xf44c;',
395
+ "ios-ionic-outline" => '&#xf44e;',
396
+ "ios-keypad" => '&#xf450;',
397
+ "ios-keypad-outline" => '&#xf44f;',
398
+ "ios-lightbulb" => '&#xf452;',
399
+ "ios-lightbulb-outline" => '&#xf451;',
400
+ "ios-list" => '&#xf454;',
401
+ "ios-list-outline" => '&#xf453;',
402
+ "ios-location" => '&#xf456;',
403
+ "ios-location-outline" => '&#xf455;',
404
+ "ios-locked" => '&#xf458;',
405
+ "ios-locked-outline" => '&#xf457;',
406
+ "ios-loop" => '&#xf45a;',
407
+ "ios-loop-strong" => '&#xf459;',
408
+ "ios-medical" => '&#xf45c;',
409
+ "ios-medical-outline" => '&#xf45b;',
410
+ "ios-medkit" => '&#xf45e;',
411
+ "ios-medkit-outline" => '&#xf45d;',
412
+ "ios-mic" => '&#xf461;',
413
+ "ios-mic-off" => '&#xf45f;',
414
+ "ios-mic-outline" => '&#xf460;',
415
+ "ios-minus" => '&#xf464;',
416
+ "ios-minus-empty" => '&#xf462;',
417
+ "ios-minus-outline" => '&#xf463;',
418
+ "ios-monitor" => '&#xf466;',
419
+ "ios-monitor-outline" => '&#xf465;',
420
+ "ios-moon" => '&#xf468;',
421
+ "ios-moon-outline" => '&#xf467;',
422
+ "ios-more" => '&#xf46a;',
423
+ "ios-more-outline" => '&#xf469;',
424
+ "ios-musical-note" => '&#xf46b;',
425
+ "ios-musical-notes" => '&#xf46c;',
426
+ "ios-navigate" => '&#xf46e;',
427
+ "ios-navigate-outline" => '&#xf46d;',
428
+ "ios-nutrition" => '&#xf470;',
429
+ "ios-nutrition-outline" => '&#xf46f;',
430
+ "ios-paper" => '&#xf472;',
431
+ "ios-paper-outline" => '&#xf471;',
432
+ "ios-paperplane" => '&#xf474;',
433
+ "ios-paperplane-outline" => '&#xf473;',
434
+ "ios-partlysunny" => '&#xf476;',
435
+ "ios-partlysunny-outline" => '&#xf475;',
436
+ "ios-pause" => '&#xf478;',
437
+ "ios-pause-outline" => '&#xf477;',
438
+ "ios-paw" => '&#xf47a;',
439
+ "ios-paw-outline" => '&#xf479;',
440
+ "ios-people" => '&#xf47c;',
441
+ "ios-people-outline" => '&#xf47b;',
442
+ "ios-person" => '&#xf47e;',
443
+ "ios-person-outline" => '&#xf47d;',
444
+ "ios-personadd" => '&#xf480;',
445
+ "ios-personadd-outline" => '&#xf47f;',
446
+ "ios-photos" => '&#xf482;',
447
+ "ios-photos-outline" => '&#xf481;',
448
+ "ios-pie" => '&#xf484;',
449
+ "ios-pie-outline" => '&#xf483;',
450
+ "ios-pint" => '&#xf486;',
451
+ "ios-pint-outline" => '&#xf485;',
452
+ "ios-play" => '&#xf488;',
453
+ "ios-play-outline" => '&#xf487;',
454
+ "ios-plus" => '&#xf48b;',
455
+ "ios-plus-empty" => '&#xf489;',
456
+ "ios-plus-outline" => '&#xf48a;',
457
+ "ios-pricetag" => '&#xf48d;',
458
+ "ios-pricetag-outline" => '&#xf48c;',
459
+ "ios-pricetags" => '&#xf48f;',
460
+ "ios-pricetags-outline" => '&#xf48e;',
461
+ "ios-printer" => '&#xf491;',
462
+ "ios-printer-outline" => '&#xf490;',
463
+ "ios-pulse" => '&#xf493;',
464
+ "ios-pulse-strong" => '&#xf492;',
465
+ "ios-rainy" => '&#xf495;',
466
+ "ios-rainy-outline" => '&#xf494;',
467
+ "ios-recording" => '&#xf497;',
468
+ "ios-recording-outline" => '&#xf496;',
469
+ "ios-redo" => '&#xf499;',
470
+ "ios-redo-outline" => '&#xf498;',
471
+ "ios-refresh" => '&#xf49c;',
472
+ "ios-refresh-empty" => '&#xf49a;',
473
+ "ios-refresh-outline" => '&#xf49b;',
474
+ "ios-reload" => '&#xf49d;',
475
+ "ios-reverse-camera" => '&#xf49f;',
476
+ "ios-reverse-camera-outline" => '&#xf49e;',
477
+ "ios-rewind" => '&#xf4a1;',
478
+ "ios-rewind-outline" => '&#xf4a0;',
479
+ "ios-rose" => '&#xf4a3;',
480
+ "ios-rose-outline" => '&#xf4a2;',
481
+ "ios-search" => '&#xf4a5;',
482
+ "ios-search-strong" => '&#xf4a4;',
483
+ "ios-settings" => '&#xf4a7;',
484
+ "ios-settings-strong" => '&#xf4a6;',
485
+ "ios-shuffle" => '&#xf4a9;',
486
+ "ios-shuffle-strong" => '&#xf4a8;',
487
+ "ios-skipbackward" => '&#xf4ab;',
488
+ "ios-skipbackward-outline" => '&#xf4aa;',
489
+ "ios-skipforward" => '&#xf4ad;',
490
+ "ios-skipforward-outline" => '&#xf4ac;',
491
+ "ios-snowy" => '&#xf4ae;',
492
+ "ios-speedometer" => '&#xf4b0;',
493
+ "ios-speedometer-outline" => '&#xf4af;',
494
+ "ios-star" => '&#xf4b3;',
495
+ "ios-star-half" => '&#xf4b1;',
496
+ "ios-star-outline" => '&#xf4b2;',
497
+ "ios-stopwatch" => '&#xf4b5;',
498
+ "ios-stopwatch-outline" => '&#xf4b4;',
499
+ "ios-sunny" => '&#xf4b7;',
500
+ "ios-sunny-outline" => '&#xf4b6;',
501
+ "ios-telephone" => '&#xf4b9;',
502
+ "ios-telephone-outline" => '&#xf4b8;',
503
+ "ios-tennisball" => '&#xf4bb;',
504
+ "ios-tennisball-outline" => '&#xf4ba;',
505
+ "ios-thunderstorm" => '&#xf4bd;',
506
+ "ios-thunderstorm-outline" => '&#xf4bc;',
507
+ "ios-time" => '&#xf4bf;',
508
+ "ios-time-outline" => '&#xf4be;',
509
+ "ios-timer" => '&#xf4c1;',
510
+ "ios-timer-outline" => '&#xf4c0;',
511
+ "ios-toggle" => '&#xf4c3;',
512
+ "ios-toggle-outline" => '&#xf4c2;',
513
+ "ios-trash" => '&#xf4c5;',
514
+ "ios-trash-outline" => '&#xf4c4;',
515
+ "ios-undo" => '&#xf4c7;',
516
+ "ios-undo-outline" => '&#xf4c6;',
517
+ "ios-unlocked" => '&#xf4c9;',
518
+ "ios-unlocked-outline" => '&#xf4c8;',
519
+ "ios-upload" => '&#xf4cb;',
520
+ "ios-upload-outline" => '&#xf4ca;',
521
+ "ios-videocam" => '&#xf4cd;',
522
+ "ios-videocam-outline" => '&#xf4cc;',
523
+ "ios-volume-high" => '&#xf4ce;',
524
+ "ios-volume-low" => '&#xf4cf;',
525
+ "ios-wineglass" => '&#xf4d1;',
526
+ "ios-wineglass-outline" => '&#xf4d0;',
527
+ "ios-world" => '&#xf4d3;',
528
+ "ios-world-outline" => '&#xf4d2;',
529
+ "ipad" => '&#xf1f9;',
530
+ "iphone" => '&#xf1fa;',
531
+ "ipod" => '&#xf1fb;',
532
+ "jet" => '&#xf295;',
533
+ "key" => '&#xf296;',
534
+ "knife" => '&#xf297;',
535
+ "laptop" => '&#xf1fc;',
536
+ "leaf" => '&#xf1fd;',
537
+ "levels" => '&#xf298;',
538
+ "lightbulb" => '&#xf299;',
539
+ "link" => '&#xf1fe;',
540
+ "load-a" => '&#xf29a;',
541
+ "load-b" => '&#xf29b;',
542
+ "load-c" => '&#xf29c;',
543
+ "load-d" => '&#xf29d;',
544
+ "location" => '&#xf1ff;',
545
+ "lock-combination" => '&#xf4d4;',
546
+ "locked" => '&#xf200;',
547
+ "log-in" => '&#xf29e;',
548
+ "log-out" => '&#xf29f;',
549
+ "loop" => '&#xf201;',
550
+ "magnet" => '&#xf2a0;',
551
+ "male" => '&#xf2a1;',
552
+ "man" => '&#xf202;',
553
+ "map" => '&#xf203;',
554
+ "medkit" => '&#xf2a2;',
555
+ "merge" => '&#xf33f;',
556
+ "mic-a" => '&#xf204;',
557
+ "mic-b" => '&#xf205;',
558
+ "mic-c" => '&#xf206;',
559
+ "minus" => '&#xf209;',
560
+ "minus-circled" => '&#xf207;',
561
+ "minus-round" => '&#xf208;',
562
+ "model-s" => '&#xf2c1;',
563
+ "monitor" => '&#xf20a;',
564
+ "more" => '&#xf20b;',
565
+ "mouse" => '&#xf340;',
566
+ "music-note" => '&#xf20c;',
567
+ "navicon" => '&#xf20e;',
568
+ "navicon-round" => '&#xf20d;',
569
+ "navigate" => '&#xf2a3;',
570
+ "network" => '&#xf341;',
571
+ "no-smoking" => '&#xf2c2;',
572
+ "nuclear" => '&#xf2a4;',
573
+ "outlet" => '&#xf342;',
574
+ "paintbrush" => '&#xf4d5;',
575
+ "paintbucket" => '&#xf4d6;',
576
+ "paper-airplane" => '&#xf2c3;',
577
+ "paperclip" => '&#xf20f;',
578
+ "pause" => '&#xf210;',
579
+ "person" => '&#xf213;',
580
+ "person-add" => '&#xf211;',
581
+ "person-stalker" => '&#xf212;',
582
+ "pie-graph" => '&#xf2a5;',
583
+ "pin" => '&#xf2a6;',
584
+ "pinpoint" => '&#xf2a7;',
585
+ "pizza" => '&#xf2a8;',
586
+ "plane" => '&#xf214;',
587
+ "planet" => '&#xf343;',
588
+ "play" => '&#xf215;',
589
+ "playstation" => '&#xf30a;',
590
+ "plus" => '&#xf218;',
591
+ "plus-circled" => '&#xf216;',
592
+ "plus-round" => '&#xf217;',
593
+ "podium" => '&#xf344;',
594
+ "pound" => '&#xf219;',
595
+ "power" => '&#xf2a9;',
596
+ "pricetag" => '&#xf2aa;',
597
+ "pricetags" => '&#xf2ab;',
598
+ "printer" => '&#xf21a;',
599
+ "pull-request" => '&#xf345;',
600
+ "qr-scanner" => '&#xf346;',
601
+ "quote" => '&#xf347;',
602
+ "radio-waves" => '&#xf2ac;',
603
+ "record" => '&#xf21b;',
604
+ "refresh" => '&#xf21c;',
605
+ "reply" => '&#xf21e;',
606
+ "reply-all" => '&#xf21d;',
607
+ "ribbon-a" => '&#xf348;',
608
+ "ribbon-b" => '&#xf349;',
609
+ "sad" => '&#xf34a;',
610
+ "sad-outline" => '&#xf4d7;',
611
+ "scissors" => '&#xf34b;',
612
+ "search" => '&#xf21f;',
613
+ "settings" => '&#xf2ad;',
614
+ "share" => '&#xf220;',
615
+ "shuffle" => '&#xf221;',
616
+ "skip-backward" => '&#xf222;',
617
+ "skip-forward" => '&#xf223;',
618
+ "social-android" => '&#xf225;',
619
+ "social-android-outline" => '&#xf224;',
620
+ "social-angular" => '&#xf4d9;',
621
+ "social-angular-outline" => '&#xf4d8;',
622
+ "social-apple" => '&#xf227;',
623
+ "social-apple-outline" => '&#xf226;',
624
+ "social-bitcoin" => '&#xf2af;',
625
+ "social-bitcoin-outline" => '&#xf2ae;',
626
+ "social-buffer" => '&#xf229;',
627
+ "social-buffer-outline" => '&#xf228;',
628
+ "social-chrome" => '&#xf4db;',
629
+ "social-chrome-outline" => '&#xf4da;',
630
+ "social-codepen" => '&#xf4dd;',
631
+ "social-codepen-outline" => '&#xf4dc;',
632
+ "social-css3" => '&#xf4df;',
633
+ "social-css3-outline" => '&#xf4de;',
634
+ "social-designernews" => '&#xf22b;',
635
+ "social-designernews-outline" => '&#xf22a;',
636
+ "social-dribbble" => '&#xf22d;',
637
+ "social-dribbble-outline" => '&#xf22c;',
638
+ "social-dropbox" => '&#xf22f;',
639
+ "social-dropbox-outline" => '&#xf22e;',
640
+ "social-euro" => '&#xf4e1;',
641
+ "social-euro-outline" => '&#xf4e0;',
642
+ "social-facebook" => '&#xf231;',
643
+ "social-facebook-outline" => '&#xf230;',
644
+ "social-foursquare" => '&#xf34d;',
645
+ "social-foursquare-outline" => '&#xf34c;',
646
+ "social-freebsd-devil" => '&#xf2c4;',
647
+ "social-github" => '&#xf233;',
648
+ "social-github-outline" => '&#xf232;',
649
+ "social-google" => '&#xf34f;',
650
+ "social-google-outline" => '&#xf34e;',
651
+ "social-googleplus" => '&#xf235;',
652
+ "social-googleplus-outline" => '&#xf234;',
653
+ "social-hackernews" => '&#xf237;',
654
+ "social-hackernews-outline" => '&#xf236;',
655
+ "social-html5" => '&#xf4e3;',
656
+ "social-html5-outline" => '&#xf4e2;',
657
+ "social-instagram" => '&#xf351;',
658
+ "social-instagram-outline" => '&#xf350;',
659
+ "social-javascript" => '&#xf4e5;',
660
+ "social-javascript-outline" => '&#xf4e4;',
661
+ "social-linkedin" => '&#xf239;',
662
+ "social-linkedin-outline" => '&#xf238;',
663
+ "social-markdown" => '&#xf4e6;',
664
+ "social-nodejs" => '&#xf4e7;',
665
+ "social-octocat" => '&#xf4e8;',
666
+ "social-pinterest" => '&#xf2b1;',
667
+ "social-pinterest-outline" => '&#xf2b0;',
668
+ "social-python" => '&#xf4e9;',
669
+ "social-reddit" => '&#xf23b;',
670
+ "social-reddit-outline" => '&#xf23a;',
671
+ "social-rss" => '&#xf23d;',
672
+ "social-rss-outline" => '&#xf23c;',
673
+ "social-sass" => '&#xf4ea;',
674
+ "social-skype" => '&#xf23f;',
675
+ "social-skype-outline" => '&#xf23e;',
676
+ "social-snapchat" => '&#xf4ec;',
677
+ "social-snapchat-outline" => '&#xf4eb;',
678
+ "social-tumblr" => '&#xf241;',
679
+ "social-tumblr-outline" => '&#xf240;',
680
+ "social-tux" => '&#xf2c5;',
681
+ "social-twitch" => '&#xf4ee;',
682
+ "social-twitch-outline" => '&#xf4ed;',
683
+ "social-twitter" => '&#xf243;',
684
+ "social-twitter-outline" => '&#xf242;',
685
+ "social-usd" => '&#xf353;',
686
+ "social-usd-outline" => '&#xf352;',
687
+ "social-vimeo" => '&#xf245;',
688
+ "social-vimeo-outline" => '&#xf244;',
689
+ "social-whatsapp" => '&#xf4f0;',
690
+ "social-whatsapp-outline" => '&#xf4ef;',
691
+ "social-windows" => '&#xf247;',
692
+ "social-windows-outline" => '&#xf246;',
693
+ "social-wordpress" => '&#xf249;',
694
+ "social-wordpress-outline" => '&#xf248;',
695
+ "social-yahoo" => '&#xf24b;',
696
+ "social-yahoo-outline" => '&#xf24a;',
697
+ "social-yen" => '&#xf4f2;',
698
+ "social-yen-outline" => '&#xf4f1;',
699
+ "social-youtube" => '&#xf24d;',
700
+ "social-youtube-outline" => '&#xf24c;',
701
+ "soup-can" => '&#xf4f4;',
702
+ "soup-can-outline" => '&#xf4f3;',
703
+ "speakerphone" => '&#xf2b2;',
704
+ "speedometer" => '&#xf2b3;',
705
+ "spoon" => '&#xf2b4;',
706
+ "star" => '&#xf24e;',
707
+ "stats-bars" => '&#xf2b5;',
708
+ "steam" => '&#xf30b;',
709
+ "stop" => '&#xf24f;',
710
+ "thermometer" => '&#xf2b6;',
711
+ "thumbsdown" => '&#xf250;',
712
+ "thumbsup" => '&#xf251;',
713
+ "toggle" => '&#xf355;',
714
+ "toggle-filled" => '&#xf354;',
715
+ "transgender" => '&#xf4f5;',
716
+ "trash-a" => '&#xf252;',
717
+ "trash-b" => '&#xf253;',
718
+ "trophy" => '&#xf356;',
719
+ "tshirt" => '&#xf4f7;',
720
+ "tshirt-outline" => '&#xf4f6;',
721
+ "umbrella" => '&#xf2b7;',
722
+ "university" => '&#xf357;',
723
+ "unlocked" => '&#xf254;',
724
+ "upload" => '&#xf255;',
725
+ "usb" => '&#xf2b8;',
726
+ "videocamera" => '&#xf256;',
727
+ "volume-high" => '&#xf257;',
728
+ "volume-low" => '&#xf258;',
729
+ "volume-medium" => '&#xf259;',
730
+ "volume-mute" => '&#xf25a;',
731
+ "wand" => '&#xf358;',
732
+ "waterdrop" => '&#xf25b;',
733
+ "wifi" => '&#xf25c;',
734
+ "wineglass" => '&#xf2b9;',
735
+ "woman" => '&#xf25d;',
736
+ "wrench" => '&#xf2ba;',
737
+ "xbox" => '&#xf30c;',
738
+ ));
739
+ }
740
+ add_filter('siteorigin_widgets_icons_ionicons', 'siteorigin_widgets_icons_ionicons_filter');
js/lib/pikaday.css ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @charset "UTF-8";
2
+
3
+ /*!
4
+ * Pikaday
5
+ * Copyright © 2014 David Bushell | BSD & MIT license | http://dbushell.com/
6
+ */
7
+
8
+ .pika-single {
9
+ z-index: 9999;
10
+ display: block;
11
+ position: relative;
12
+ color: #333;
13
+ background: #fff;
14
+ border: 1px solid #ccc;
15
+ border-bottom-color: #bbb;
16
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
17
+ }
18
+
19
+ /*
20
+ clear child float (pika-lendar), using the famous micro clearfix hack
21
+ http://nicolasgallagher.com/micro-clearfix-hack/
22
+ */
23
+ .pika-single:before,
24
+ .pika-single:after {
25
+ content: " ";
26
+ display: table;
27
+ }
28
+ .pika-single:after { clear: both }
29
+ .pika-single { *zoom: 1 }
30
+
31
+ .pika-single.is-hidden {
32
+ display: none;
33
+ }
34
+
35
+ .pika-single.is-bound {
36
+ position: absolute;
37
+ box-shadow: 0 5px 15px -5px rgba(0,0,0,.5);
38
+ }
39
+
40
+ .pika-lendar {
41
+ float: left;
42
+ width: 240px;
43
+ margin: 8px;
44
+ }
45
+
46
+ .pika-title {
47
+ position: relative;
48
+ text-align: center;
49
+ }
50
+
51
+ .pika-label {
52
+ display: inline-block;
53
+ *display: inline;
54
+ position: relative;
55
+ z-index: 9999;
56
+ overflow: hidden;
57
+ margin: 0;
58
+ padding: 5px 3px;
59
+ font-size: 14px;
60
+ line-height: 20px;
61
+ font-weight: bold;
62
+ background-color: #fff;
63
+ }
64
+ .pika-title select {
65
+ cursor: pointer;
66
+ position: absolute;
67
+ z-index: 9998;
68
+ margin: 0;
69
+ left: 0;
70
+ top: 5px;
71
+ filter: alpha(opacity=0);
72
+ opacity: 0;
73
+ }
74
+
75
+ .pika-prev,
76
+ .pika-next {
77
+ display: block;
78
+ cursor: pointer;
79
+ position: relative;
80
+ outline: none;
81
+ border: 0;
82
+ padding: 0;
83
+ width: 20px;
84
+ height: 30px;
85
+ /* hide text using text-indent trick, using width value (it's enough) */
86
+ text-indent: 20px;
87
+ white-space: nowrap;
88
+ overflow: hidden;
89
+ background-color: transparent;
90
+ background-position: center center;
91
+ background-repeat: no-repeat;
92
+ background-size: 75% 75%;
93
+ opacity: .5;
94
+ *position: absolute;
95
+ *top: 0;
96
+ }
97
+
98
+ .pika-prev:hover,
99
+ .pika-next:hover {
100
+ opacity: 1;
101
+ }
102
+
103
+ .pika-prev,
104
+ .is-rtl .pika-next {
105
+ float: left;
106
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg==');
107
+ *left: 0;
108
+ }
109
+
110
+ .pika-next,
111
+ .is-rtl .pika-prev {
112
+ float: right;
113
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII=');
114
+ *right: 0;
115
+ }
116
+
117
+ .pika-prev.is-disabled,
118
+ .pika-next.is-disabled {
119
+ cursor: default;
120
+ opacity: .2;
121
+ }
122
+
123
+ .pika-select {
124
+ display: inline-block;
125
+ *display: inline;
126
+ }
127
+
128
+ .pika-table {
129
+ width: 100%;
130
+ border-collapse: collapse;
131
+ border-spacing: 0;
132
+ border: 0;
133
+ }
134
+
135
+ .pika-table th,
136
+ .pika-table td {
137
+ width: 14.285714285714286%;
138
+ padding: 0;
139
+ }
140
+
141
+ .pika-table th {
142
+ color: #999;
143
+ font-size: 12px;
144
+ line-height: 25px;
145
+ font-weight: bold;
146
+ text-align: center;
147
+ }
148
+
149
+ .pika-button {
150
+ cursor: pointer;
151
+ display: block;
152
+ box-sizing: border-box;
153
+ -moz-box-sizing: border-box;
154
+ outline: none;
155
+ border: 0;
156
+ margin: 0;
157
+ width: 100%;
158
+ padding: 5px;
159
+ color: #666;
160
+ font-size: 12px;
161
+ line-height: 15px;
162
+ text-align: right;
163
+ background: #f5f5f5;
164
+ }
165
+
166
+ .pika-week {
167
+ font-size: 11px;
168
+ color: #999;
169
+ }
170
+
171
+ .is-today .pika-button {
172
+ color: #33aaff;
173
+ font-weight: bold;
174
+ }
175
+
176
+ .is-selected .pika-button,
177
+ .has-event .pika-button {
178
+ color: #fff;
179
+ font-weight: bold;
180
+ background: #33aaff;
181
+ box-shadow: inset 0 1px 3px #178fe5;
182
+ border-radius: 3px;
183
+ }
184
+
185
+ .has-event .pika-button {
186
+ background: #005da9;
187
+ box-shadow: inset 0 1px 3px #0076c9;
188
+ }
189
+
190
+ .is-disabled .pika-button,
191
+ .is-inrange .pika-button {
192
+ background: #D5E9F7;
193
+ }
194
+
195
+ .is-startrange .pika-button {
196
+ color: #fff;
197
+ background: #6CB31D;
198
+ box-shadow: none;
199
+ border-radius: 3px;
200
+ }
201
+
202
+ .is-endrange .pika-button {
203
+ color: #fff;
204
+ background: #33aaff;
205
+ box-shadow: none;
206
+ border-radius: 3px;
207
+ }
208
+
209
+ .is-disabled .pika-button {
210
+ pointer-events: none;
211
+ cursor: default;
212
+ color: #999;
213
+ opacity: .3;
214
+ }
215
+
216
+ .is-outside-current-month .pika-button {
217
+ color: #999;
218
+ opacity: .3;
219
+ }
220
+
221
+ .is-selection-disabled {
222
+ pointer-events: none;
223
+ cursor: default;
224
+ }
225
+
226
+ .pika-button:hover,
227
+ .pika-row.pick-whole-week:hover .pika-button {
228
+ color: #fff;
229
+ background: #ff8000;
230
+ box-shadow: none;
231
+ border-radius: 3px;
232
+ }
233
+
234
+ /* styling for abbr */
235
+ .pika-table abbr {
236
+ border-bottom: none;
237
+ cursor: help;
238
+ }
239
+
js/lib/pikaday.js ADDED
@@ -0,0 +1,1236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Pikaday
3
+ *
4
+ * Copyright © 2014 David Bushell | BSD & MIT license | https://github.com/dbushell/Pikaday
5
+ */
6
+
7
+ (function (root, factory)
8
+ {
9
+ 'use strict';
10
+
11
+ var moment;
12
+ if (typeof exports === 'object') {
13
+ // CommonJS module
14
+ // Load moment.js as an optional dependency
15
+ try { moment = require('moment'); } catch (e) {}
16
+ module.exports = factory(moment);
17
+ } else if (typeof define === 'function' && define.amd) {
18
+ // AMD. Register as an anonymous module.
19
+ define(function (req)
20
+ {
21
+ // Load moment.js as an optional dependency
22
+ var id = 'moment';
23
+ try { moment = req(id); } catch (e) {}
24
+ return factory(moment);
25
+ });
26
+ } else {
27
+ root.Pikaday = factory(root.moment);
28
+ }
29
+ }(this, function (moment)
30
+ {
31
+ 'use strict';
32
+
33
+ /**
34
+ * feature detection and helper functions
35
+ */
36
+ var hasMoment = typeof moment === 'function',
37
+
38
+ hasEventListeners = !!window.addEventListener,
39
+
40
+ document = window.document,
41
+
42
+ sto = window.setTimeout,
43
+
44
+ addEvent = function(el, e, callback, capture)
45
+ {
46
+ if (hasEventListeners) {
47
+ el.addEventListener(e, callback, !!capture);
48
+ } else {
49
+ el.attachEvent('on' + e, callback);
50
+ }
51
+ },
52
+
53
+ removeEvent = function(el, e, callback, capture)
54
+ {
55
+ if (hasEventListeners) {
56
+ el.removeEventListener(e, callback, !!capture);
57
+ } else {
58
+ el.detachEvent('on' + e, callback);
59
+ }
60
+ },
61
+
62
+ trim = function(str)
63
+ {
64
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
65
+ },
66
+
67
+ hasClass = function(el, cn)
68
+ {
69
+ return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
70
+ },
71
+
72
+ addClass = function(el, cn)
73
+ {
74
+ if (!hasClass(el, cn)) {
75
+ el.className = (el.className === '') ? cn : el.className + ' ' + cn;
76
+ }
77
+ },
78
+
79
+ removeClass = function(el, cn)
80
+ {
81
+ el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
82
+ },
83
+
84
+ isArray = function(obj)
85
+ {
86
+ return (/Array/).test(Object.prototype.toString.call(obj));
87
+ },
88
+
89
+ isDate = function(obj)
90
+ {
91
+ return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
92
+ },
93
+
94
+ isWeekend = function(date)
95
+ {
96
+ var day = date.getDay();
97
+ return day === 0 || day === 6;
98
+ },
99
+
100
+ isLeapYear = function(year)
101
+ {
102
+ // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
103
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
104
+ },
105
+
106
+ getDaysInMonth = function(year, month)
107
+ {
108
+ return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
109
+ },
110
+
111
+ setToStartOfDay = function(date)
112
+ {
113
+ if (isDate(date)) date.setHours(0,0,0,0);
114
+ },
115
+
116
+ compareDates = function(a,b)
117
+ {
118
+ // weak date comparison (use setToStartOfDay(date) to ensure correct result)
119
+ return a.getTime() === b.getTime();
120
+ },
121
+
122
+ extend = function(to, from, overwrite)
123
+ {
124
+ var prop, hasProp;
125
+ for (prop in from) {
126
+ hasProp = to[prop] !== undefined;
127
+ if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
128
+ if (isDate(from[prop])) {
129
+ if (overwrite) {
130
+ to[prop] = new Date(from[prop].getTime());
131
+ }
132
+ }
133
+ else if (isArray(from[prop])) {
134
+ if (overwrite) {
135
+ to[prop] = from[prop].slice(0);
136
+ }
137
+ } else {
138
+ to[prop] = extend({}, from[prop], overwrite);
139
+ }
140
+ } else if (overwrite || !hasProp) {
141
+ to[prop] = from[prop];
142
+ }
143
+ }
144
+ return to;
145
+ },
146
+
147
+ fireEvent = function(el, eventName, data)
148
+ {
149
+ var ev;
150
+
151
+ if (document.createEvent) {
152
+ ev = document.createEvent('HTMLEvents');
153
+ ev.initEvent(eventName, true, false);
154
+ ev = extend(ev, data);
155
+ el.dispatchEvent(ev);
156
+ } else if (document.createEventObject) {
157
+ ev = document.createEventObject();
158
+ ev = extend(ev, data);
159
+ el.fireEvent('on' + eventName, ev);
160
+ }
161
+ },
162
+
163
+ adjustCalendar = function(calendar) {
164
+ if (calendar.month < 0) {
165
+ calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
166
+ calendar.month += 12;
167
+ }
168
+ if (calendar.month > 11) {
169
+ calendar.year += Math.floor(Math.abs(calendar.month)/12);
170
+ calendar.month -= 12;
171
+ }
172
+ return calendar;
173
+ },
174
+
175
+ /**
176
+ * defaults and localisation
177
+ */
178
+ defaults = {
179
+
180
+ // bind the picker to a form field
181
+ field: null,
182
+
183
+ // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
184
+ bound: undefined,
185
+
186
+ // position of the datepicker, relative to the field (default to bottom & left)
187
+ // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
188
+ position: 'bottom left',
189
+
190
+ // automatically fit in the viewport even if it means repositioning from the position option
191
+ reposition: true,
192
+
193
+ // the default output format for `.toString()` and `field` value
194
+ format: 'YYYY-MM-DD',
195
+
196
+ // the toString function which gets passed a current date object and format
197
+ // and returns a string
198
+ toString: null,
199
+
200
+ // used to create date object from current input string
201
+ parse: null,
202
+
203
+ // the initial date to view when first opened
204
+ defaultDate: null,
205
+
206
+ // make the `defaultDate` the initial selected value
207
+ setDefaultDate: false,
208
+
209
+ // first day of week (0: Sunday, 1: Monday etc)
210
+ firstDay: 0,
211
+
212
+ // the default flag for moment's strict date parsing
213
+ formatStrict: false,
214
+
215
+ // the minimum/earliest date that can be selected
216
+ minDate: null,
217
+ // the maximum/latest date that can be selected
218
+ maxDate: null,
219
+
220
+ // number of years either side, or array of upper/lower range
221
+ yearRange: 10,
222
+
223
+ // show week numbers at head of row
224
+ showWeekNumber: false,
225
+
226
+ // Week picker mode
227
+ pickWholeWeek: false,
228
+
229
+ // used internally (don't config outside)
230
+ minYear: 0,
231
+ maxYear: 9999,
232
+ minMonth: undefined,
233
+ maxMonth: undefined,
234
+
235
+ startRange: null,
236
+ endRange: null,
237
+
238
+ isRTL: false,
239
+
240
+ // Additional text to append to the year in the calendar title
241
+ yearSuffix: '',
242
+
243
+ // Render the month after year in the calendar title
244
+ showMonthAfterYear: false,
245
+
246
+ // Render days of the calendar grid that fall in the next or previous month
247
+ showDaysInNextAndPreviousMonths: false,
248
+
249
+ // Allows user to select days that fall in the next or previous month
250
+ enableSelectionDaysInNextAndPreviousMonths: false,
251
+
252
+ // how many months are visible
253
+ numberOfMonths: 1,
254
+
255
+ // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
256
+ // only used for the first display or when a selected date is not visible
257
+ mainCalendar: 'left',
258
+
259
+ // Specify a DOM element to render the calendar in
260
+ container: undefined,
261
+
262
+ // Blur field when date is selected
263
+ blurFieldOnSelect : true,
264
+
265
+ // internationalization
266
+ i18n: {
267
+ previousMonth : 'Previous Month',
268
+ nextMonth : 'Next Month',
269
+ months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
270
+ weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
271
+ weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
272
+ },
273
+
274
+ // Theme Classname
275
+ theme: null,
276
+
277
+ // events array
278
+ events: [],
279
+
280
+ // callback function
281
+ onSelect: null,
282
+ onOpen: null,
283
+ onClose: null,
284
+ onDraw: null
285
+ },
286
+
287
+
288
+ /**
289
+ * templating functions to abstract HTML rendering
290
+ */
291
+ renderDayName = function(opts, day, abbr)
292
+ {
293
+ day += opts.firstDay;
294
+ while (day >= 7) {
295
+ day -= 7;
296
+ }
297
+ return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
298
+ },
299
+
300
+ renderDay = function(opts)
301
+ {
302
+ var arr = [];
303
+ var ariaSelected = 'false';
304
+ if (opts.isEmpty) {
305
+ if (opts.showDaysInNextAndPreviousMonths) {
306
+ arr.push('is-outside-current-month');
307
+
308
+ if(!opts.enableSelectionDaysInNextAndPreviousMonths) {
309
+ arr.push('is-selection-disabled');
310
+ }
311
+
312
+ } else {
313
+ return '<td class="is-empty"></td>';
314
+ }
315
+ }
316
+ if (opts.isDisabled) {
317
+ arr.push('is-disabled');
318
+ }
319
+ if (opts.isToday) {
320
+ arr.push('is-today');
321
+ }
322
+ if (opts.isSelected) {
323
+ arr.push('is-selected');
324
+ ariaSelected = 'true';
325
+ }
326
+ if (opts.hasEvent) {
327
+ arr.push('has-event');
328
+ }
329
+ if (opts.isInRange) {
330
+ arr.push('is-inrange');
331
+ }
332
+ if (opts.isStartRange) {
333
+ arr.push('is-startrange');
334
+ }
335
+ if (opts.isEndRange) {
336
+ arr.push('is-endrange');
337
+ }
338
+ return '<td data-day="' + opts.day + '" class="' + arr.join(' ') + '" aria-selected="' + ariaSelected + '">' +
339
+ '<button class="pika-button pika-day" type="button" ' +
340
+ 'data-pika-year="' + opts.year + '" data-pika-month="' + opts.month + '" data-pika-day="' + opts.day + '">' +
341
+ opts.day +
342
+ '</button>' +
343
+ '</td>';
344
+ },
345
+
346
+ renderWeek = function (d, m, y) {
347
+ // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
348
+ var onejan = new Date(y, 0, 1),
349
+ weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
350
+ return '<td class="pika-week">' + weekNum + '</td>';
351
+ },
352
+
353
+ renderRow = function(days, isRTL, pickWholeWeek, isRowSelected)
354
+ {
355
+ return '<tr class="pika-row' + (pickWholeWeek ? ' pick-whole-week' : '') + (isRowSelected ? ' is-selected' : '') + '">' + (isRTL ? days.reverse() : days).join('') + '</tr>';
356
+ },
357
+
358
+ renderBody = function(rows)
359
+ {
360
+ return '<tbody>' + rows.join('') + '</tbody>';
361
+ },
362
+
363
+ renderHead = function(opts)
364
+ {
365
+ var i, arr = [];
366
+ if (opts.showWeekNumber) {
367
+ arr.push('<th></th>');
368
+ }
369
+ for (i = 0; i < 7; i++) {
370
+ arr.push('<th scope="col"><abbr title="' + renderDayName(opts, i) + '">' + renderDayName(opts, i, true) + '</abbr></th>');
371
+ }
372
+ return '<thead><tr>' + (opts.isRTL ? arr.reverse() : arr).join('') + '</tr></thead>';
373
+ },
374
+
375
+ renderTitle = function(instance, c, year, month, refYear, randId)
376
+ {
377
+ var i, j, arr,
378
+ opts = instance._o,
379
+ isMinYear = year === opts.minYear,
380
+ isMaxYear = year === opts.maxYear,
381
+ html = '<div id="' + randId + '" class="pika-title" role="heading" aria-live="assertive">',
382
+ monthHtml,
383
+ yearHtml,
384
+ prev = true,
385
+ next = true;
386
+
387
+ for (arr = [], i = 0; i < 12; i++) {
388
+ arr.push('<option value="' + (year === refYear ? i - c : 12 + i - c) + '"' +
389
+ (i === month ? ' selected="selected"': '') +
390
+ ((isMinYear && i < opts.minMonth) || (isMaxYear && i > opts.maxMonth) ? 'disabled="disabled"' : '') + '>' +
391
+ opts.i18n.months[i] + '</option>');
392
+ }
393
+
394
+ monthHtml = '<div class="pika-label">' + opts.i18n.months[month] + '<select class="pika-select pika-select-month" tabindex="-1">' + arr.join('') + '</select></div>';
395
+
396
+ if (isArray(opts.yearRange)) {
397
+ i = opts.yearRange[0];
398
+ j = opts.yearRange[1] + 1;
399
+ } else {
400
+ i = year - opts.yearRange;
401
+ j = 1 + year + opts.yearRange;
402
+ }
403
+
404
+ for (arr = []; i < j && i <= opts.maxYear; i++) {
405
+ if (i >= opts.minYear) {
406
+ arr.push('<option value="' + i + '"' + (i === year ? ' selected="selected"': '') + '>' + (i) + '</option>');
407
+ }
408
+ }
409
+ yearHtml = '<div class="pika-label">' + year + opts.yearSuffix + '<select class="pika-select pika-select-year" tabindex="-1">' + arr.join('') + '</select></div>';
410
+
411
+ if (opts.showMonthAfterYear) {
412
+ html += yearHtml + monthHtml;
413
+ } else {
414
+ html += monthHtml + yearHtml;
415
+ }
416
+
417
+ if (isMinYear && (month === 0 || opts.minMonth >= month)) {
418
+ prev = false;
419
+ }
420
+
421
+ if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
422
+ next = false;
423
+ }
424
+
425
+ if (c === 0) {
426
+ html += '<button class="pika-prev' + (prev ? '' : ' is-disabled') + '" type="button">' + opts.i18n.previousMonth + '</button>';
427
+ }
428
+ if (c === (instance._o.numberOfMonths - 1) ) {
429
+ html += '<button class="pika-next' + (next ? '' : ' is-disabled') + '" type="button">' + opts.i18n.nextMonth + '</button>';
430
+ }
431
+
432
+ return html += '</div>';
433
+ },
434
+
435
+ renderTable = function(opts, data, randId)
436
+ {
437
+ return '<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="' + randId + '">' + renderHead(opts) + renderBody(data) + '</table>';
438
+ },
439
+
440
+
441
+ /**
442
+ * Pikaday constructor
443
+ */
444
+ Pikaday = function(options)
445
+ {
446
+ var self = this,
447
+ opts = self.config(options);
448
+
449
+ self._onMouseDown = function(e)
450
+ {
451
+ if (!self._v) {
452
+ return;
453
+ }
454
+ e = e || window.event;
455
+ var target = e.target || e.srcElement;
456
+ if (!target) {
457
+ return;
458
+ }
459
+
460
+ if (!hasClass(target, 'is-disabled')) {
461
+ if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty') && !hasClass(target.parentNode, 'is-disabled')) {
462
+ self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
463
+ if (opts.bound) {
464
+ sto(function() {
465
+ self.hide();
466
+ if (opts.blurFieldOnSelect && opts.field) {
467
+ opts.field.blur();
468
+ }
469
+ }, 100);
470
+ }
471
+ }
472
+ else if (hasClass(target, 'pika-prev')) {
473
+ self.prevMonth();
474
+ }
475
+ else if (hasClass(target, 'pika-next')) {
476
+ self.nextMonth();
477
+ }
478
+ }
479
+ if (!hasClass(target, 'pika-select')) {
480
+ // if this is touch event prevent mouse events emulation
481
+ if (e.preventDefault) {
482
+ e.preventDefault();
483
+ } else {
484
+ e.returnValue = false;
485
+ return false;
486
+ }
487
+ } else {
488
+ self._c = true;
489
+ }
490
+ };
491
+
492
+ self._onChange = function(e)
493
+ {
494
+ e = e || window.event;
495
+ var target = e.target || e.srcElement;
496
+ if (!target) {
497
+ return;
498
+ }
499
+ if (hasClass(target, 'pika-select-month')) {
500
+ self.gotoMonth(target.value);
501
+ }
502
+ else if (hasClass(target, 'pika-select-year')) {
503
+ self.gotoYear(target.value);
504
+ }
505
+ };
506
+
507
+ self._onKeyChange = function(e)
508
+ {
509
+ e = e || window.event;
510
+
511
+ if (self.isVisible()) {
512
+
513
+ switch(e.keyCode){
514
+ case 13:
515
+ case 27:
516
+ if (opts.field) {
517
+ opts.field.blur();
518
+ }
519
+ break;
520
+ case 37:
521
+ e.preventDefault();
522
+ self.adjustDate('subtract', 1);
523
+ break;
524
+ case 38:
525
+ self.adjustDate('subtract', 7);
526
+ break;
527
+ case 39:
528
+ self.adjustDate('add', 1);
529
+ break;
530
+ case 40:
531
+ self.adjustDate('add', 7);
532
+ break;
533
+ }
534
+ }
535
+ };
536
+
537
+ self._onInputChange = function(e)
538
+ {
539
+ var date;
540
+
541
+ if (e.firedBy === self) {
542
+ return;
543
+ }
544
+ if (opts.parse) {
545
+ date = opts.parse(opts.field.value, opts.format);
546
+ } else if (hasMoment) {
547
+ date = moment(opts.field.value, opts.format, opts.formatStrict);
548
+ date = (date && date.isValid()) ? date.toDate() : null;
549
+ }
550
+ else {
551
+ date = new Date(Date.parse(opts.field.value));
552
+ }
553
+ if (isDate(date)) {
554
+ self.setDate(date);
555
+ }
556
+ if (!self._v) {
557
+ self.show();
558
+ }
559
+ };
560
+
561
+ self._onInputFocus = function()
562
+ {
563
+ self.show();
564
+ };
565
+
566
+ self._onInputClick = function()
567
+ {
568
+ self.show();
569
+ };
570
+
571
+ self._onInputBlur = function()
572
+ {
573
+ // IE allows pika div to gain focus; catch blur the input field
574
+ var pEl = document.activeElement;
575
+ do {
576
+ if (hasClass(pEl, 'pika-single')) {
577
+ return;
578
+ }
579
+ }
580
+ while ((pEl = pEl.parentNode));
581
+
582
+ if (!self._c) {
583
+ self._b = sto(function() {
584
+ self.hide();
585
+ }, 50);
586
+ }
587
+ self._c = false;
588
+ };
589
+
590
+ self._onClick = function(e)
591
+ {
592
+ e = e || window.event;
593
+ var target = e.target || e.srcElement,
594
+ pEl = target;
595
+ if (!target) {
596
+ return;
597
+ }
598
+ if (!hasEventListeners && hasClass(target, 'pika-select')) {
599
+ if (!target.onchange) {
600
+ target.setAttribute('onchange', 'return;');
601
+ addEvent(target, 'change', self._onChange);
602
+ }
603
+ }
604
+ do {
605
+ if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
606
+ return;
607
+ }
608
+ }
609
+ while ((pEl = pEl.parentNode));
610
+ if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
611
+ self.hide();
612
+ }
613
+ };
614
+
615
+ self.el = document.createElement('div');
616
+ self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '') + (opts.theme ? ' ' + opts.theme : '');
617
+
618
+ addEvent(self.el, 'mousedown', self._onMouseDown, true);
619
+ addEvent(self.el, 'touchend', self._onMouseDown, true);
620
+ addEvent(self.el, 'change', self._onChange);
621
+ addEvent(document, 'keydown', self._onKeyChange);
622
+
623
+ if (opts.field) {
624
+ if (opts.container) {
625
+ opts.container.appendChild(self.el);
626
+ } else if (opts.bound) {
627
+ document.body.appendChild(self.el);
628
+ } else {
629
+ opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
630
+ }
631
+ addEvent(opts.field, 'change', self._onInputChange);
632
+
633
+ if (!opts.defaultDate) {
634
+ if (hasMoment && opts.field.value) {
635
+ opts.defaultDate = moment(opts.field.value, opts.format).toDate();
636
+ } else {
637
+ opts.defaultDate = new Date(Date.parse(opts.field.value));
638
+ }
639
+ opts.setDefaultDate = true;
640
+ }
641
+ }
642
+
643
+ var defDate = opts.defaultDate;
644
+
645
+ if (isDate(defDate)) {
646
+ if (opts.setDefaultDate) {
647
+ self.setDate(defDate, true);
648
+ } else {
649
+ self.gotoDate(defDate);
650
+ }
651
+ } else {
652
+ self.gotoDate(new Date());
653
+ }
654
+
655
+ if (opts.bound) {
656
+ this.hide();
657
+ self.el.className += ' is-bound';
658
+ addEvent(opts.trigger, 'click', self._onInputClick);
659
+ addEvent(opts.trigger, 'focus', self._onInputFocus);
660
+ addEvent(opts.trigger, 'blur', self._onInputBlur);
661
+ } else {
662
+ this.show();
663
+ }
664
+ };
665
+
666
+
667
+ /**
668
+ * public Pikaday API
669
+ */
670
+ Pikaday.prototype = {
671
+
672
+
673
+ /**
674
+ * configure functionality
675
+ */
676
+ config: function(options)
677
+ {
678
+ if (!this._o) {
679
+ this._o = extend({}, defaults, true);
680
+ }
681
+
682
+ var opts = extend(this._o, options, true);
683
+
684
+ opts.isRTL = !!opts.isRTL;
685
+
686
+ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
687
+
688
+ opts.theme = (typeof opts.theme) === 'string' && opts.theme ? opts.theme : null;
689
+
690
+ opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
691
+
692
+ opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
693
+
694
+ opts.disableWeekends = !!opts.disableWeekends;
695
+
696
+ opts.disableDayFn = (typeof opts.disableDayFn) === 'function' ? opts.disableDayFn : null;
697
+
698
+ var nom = parseInt(opts.numberOfMonths, 10) || 1;
699
+ opts.numberOfMonths = nom > 4 ? 4 : nom;
700
+
701
+ if (!isDate(opts.minDate)) {
702
+ opts.minDate = false;
703
+ }
704
+ if (!isDate(opts.maxDate)) {
705
+ opts.maxDate = false;
706
+ }
707
+ if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
708
+ opts.maxDate = opts.minDate = false;
709
+ }
710
+ if (opts.minDate) {
711
+ this.setMinDate(opts.minDate);
712
+ }
713
+ if (opts.maxDate) {
714
+ this.setMaxDate(opts.maxDate);
715
+ }
716
+
717
+ if (isArray(opts.yearRange)) {
718
+ var fallback = new Date().getFullYear() - 10;
719
+ opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
720
+ opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
721
+ } else {
722
+ opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
723
+ if (opts.yearRange > 100) {
724
+ opts.yearRange = 100;
725
+ }
726
+ }
727
+
728
+ return opts;
729
+ },
730
+
731
+ /**
732
+ * return a formatted string of the current selection (using Moment.js if available)
733
+ */
734
+ toString: function(format)
735
+ {
736
+ format = format || this._o.format;
737
+ if (!isDate(this._d)) {
738
+ return '';
739
+ }
740
+ if (this._o.toString) {
741
+ return this._o.toString(this._d, format);
742
+ }
743
+ if (hasMoment) {
744
+ return moment(this._d).format(format);
745
+ }
746
+ return this._d.toDateString();
747
+ },
748
+
749
+ /**
750
+ * return a Moment.js object of the current selection (if available)
751
+ */
752
+ getMoment: function()
753
+ {
754
+ return hasMoment ? moment(this._d) : null;
755
+ },
756
+
757
+ /**
758
+ * set the current selection from a Moment.js object (if available)
759
+ */
760
+ setMoment: function(date, preventOnSelect)
761
+ {
762
+ if (hasMoment && moment.isMoment(date)) {
763
+ this.setDate(date.toDate(), preventOnSelect);
764
+ }
765
+ },
766
+
767
+ /**
768
+ * return a Date object of the current selection
769
+ */
770
+ getDate: function()
771
+ {
772
+ return isDate(this._d) ? new Date(this._d.getTime()) : null;
773
+ },
774
+
775
+ /**
776
+ * set the current selection
777
+ */
778
+ setDate: function(date, preventOnSelect)
779
+ {
780
+ if (!date) {
781
+ this._d = null;
782
+
783
+ if (this._o.field) {
784
+ this._o.field.value = '';
785
+ fireEvent(this._o.field, 'change', { firedBy: this });
786
+ }
787
+
788
+ return this.draw();
789
+ }
790
+ if (typeof date === 'string') {
791
+ date = new Date(Date.parse(date));
792
+ }
793
+ if (!isDate(date)) {
794
+ return;
795
+ }
796
+
797
+ var min = this._o.minDate,
798
+ max = this._o.maxDate;
799
+
800
+ if (isDate(min) && date < min) {
801
+ date = min;
802
+ } else if (isDate(max) && date > max) {
803
+ date = max;
804
+ }
805
+
806
+ this._d = new Date(date.getTime());
807
+ setToStartOfDay(this._d);
808
+ this.gotoDate(this._d);
809
+
810
+ if (this._o.field) {
811
+ this._o.field.value = this.toString();
812
+ fireEvent(this._o.field, 'change', { firedBy: this });
813
+ }
814
+ if (!preventOnSelect && typeof this._o.onSelect === 'function') {
815
+ this._o.onSelect.call(this, this.getDate());
816
+ }
817
+ },
818
+
819
+ /**
820
+ * change view to a specific date
821
+ */
822
+ gotoDate: function(date)
823
+ {
824
+ var newCalendar = true;
825
+
826
+ if (!isDate(date)) {
827
+ return;
828
+ }
829
+
830
+ if (this.calendars) {
831
+ var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
832
+ lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
833
+ visibleDate = date.getTime();
834
+ // get the end of the month
835
+ lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
836
+ lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
837
+ newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
838
+ }
839
+
840
+ if (newCalendar) {
841
+ this.calendars = [{
842
+ month: date.getMonth(),
843
+ year: date.getFullYear()
844
+ }];
845
+ if (this._o.mainCalendar === 'right') {
846
+ this.calendars[0].month += 1 - this._o.numberOfMonths;
847
+ }
848
+ }
849
+
850
+ this.adjustCalendars();
851
+ },
852
+
853
+ adjustDate: function(sign, days) {
854
+
855
+ var day = this.getDate() || new Date();
856
+ var difference = parseInt(days)*24*60*60*1000;
857
+
858
+ var newDay;
859
+
860
+ if (sign === 'add') {
861
+ newDay = new Date(day.valueOf() + difference);
862
+ } else if (sign === 'subtract') {
863
+ newDay = new Date(day.valueOf() - difference);
864
+ }
865
+
866
+ this.setDate(newDay);
867
+ },
868
+
869
+ adjustCalendars: function() {
870
+ this.calendars[0] = adjustCalendar(this.calendars[0]);
871
+ for (var c = 1; c < this._o.numberOfMonths; c++) {
872
+ this.calendars[c] = adjustCalendar({
873
+ month: this.calendars[0].month + c,
874
+ year: this.calendars[0].year
875
+ });
876
+ }
877
+ this.draw();
878
+ },
879
+
880
+ gotoToday: function()
881
+ {
882
+ this.gotoDate(new Date());
883
+ },
884
+
885
+ /**
886
+ * change view to a specific month (zero-index, e.g. 0: January)
887
+ */
888
+ gotoMonth: function(month)
889
+ {
890
+ if (!isNaN(month)) {
891
+ this.calendars[0].month = parseInt(month, 10);
892
+ this.adjustCalendars();
893
+ }
894
+ },
895
+
896
+ nextMonth: function()
897
+ {
898
+ this.calendars[0].month++;
899
+ this.adjustCalendars();
900
+ },
901
+
902
+ prevMonth: function()
903
+ {
904
+ this.calendars[0].month--;
905
+ this.adjustCalendars();
906
+ },
907
+
908
+ /**
909
+ * change view to a specific full year (e.g. "2012")
910
+ */
911
+ gotoYear: function(year)
912
+ {
913
+ if (!isNaN(year)) {
914
+ this.calendars[0].year = parseInt(year, 10);
915
+ this.adjustCalendars();
916
+ }
917
+ },
918
+
919
+ /**
920
+ * change the minDate
921
+ */
922
+ setMinDate: function(value)
923
+ {
924
+ if(value instanceof Date) {
925
+ setToStartOfDay(value);
926
+ this._o.minDate = value;
927
+ this._o.minYear = value.getFullYear();
928
+ this._o.minMonth = value.getMonth();
929
+ } else {
930
+ this._o.minDate = defaults.minDate;
931
+ this._o.minYear = defaults.minYear;
932
+ this._o.minMonth = defaults.minMonth;
933
+ this._o.startRange = defaults.startRange;
934
+ }
935
+
936
+ this.draw();
937
+ },
938
+
939
+ /**
940
+ * change the maxDate
941
+ */
942
+ setMaxDate: function(value)
943
+ {
944
+ if(value instanceof Date) {
945
+ setToStartOfDay(value);
946
+ this._o.maxDate = value;
947
+ this._o.maxYear = value.getFullYear();
948
+ this._o.maxMonth = value.getMonth();
949
+ } else {
950
+ this._o.maxDate = defaults.maxDate;
951
+ this._o.maxYear = defaults.maxYear;
952
+ this._o.maxMonth = defaults.maxMonth;
953
+ this._o.endRange = defaults.endRange;
954
+ }
955
+
956
+ this.draw();
957
+ },
958
+
959
+ setStartRange: function(value)
960
+ {
961
+ this._o.startRange = value;
962
+ },
963
+
964
+ setEndRange: function(value)
965
+ {
966
+ this._o.endRange = value;
967
+ },
968
+
969
+ /**
970
+ * refresh the HTML
971
+ */
972
+ draw: function(force)
973
+ {
974
+ if (!this._v && !force) {
975
+ return;
976
+ }
977
+ var opts = this._o,
978
+ minYear = opts.minYear,
979
+ maxYear = opts.maxYear,
980
+ minMonth = opts.minMonth,
981
+ maxMonth = opts.maxMonth,
982
+ html = '',
983
+ randId;
984
+
985
+ if (this._y <= minYear) {
986
+ this._y = minYear;
987
+ if (!isNaN(minMonth) && this._m < minMonth) {
988
+ this._m = minMonth;
989
+ }
990
+ }
991
+ if (this._y >= maxYear) {
992
+ this._y = maxYear;
993
+ if (!isNaN(maxMonth) && this._m > maxMonth) {
994
+ this._m = maxMonth;
995
+ }
996
+ }
997
+
998
+ randId = 'pika-title-' + Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 2);
999
+
1000
+ for (var c = 0; c < opts.numberOfMonths; c++) {
1001
+ html += '<div class="pika-lendar">' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year, randId) + this.render(this.calendars[c].year, this.calendars[c].month, randId) + '</div>';
1002
+ }
1003
+
1004
+ this.el.innerHTML = html;
1005
+
1006
+ if (opts.bound) {
1007
+ if(opts.field.type !== 'hidden') {
1008
+ sto(function() {
1009
+ opts.trigger.focus();
1010
+ }, 1);
1011
+ }
1012
+ }
1013
+
1014
+ if (typeof this._o.onDraw === 'function') {
1015
+ this._o.onDraw(this);
1016
+ }
1017
+
1018
+ if (opts.bound) {
1019
+ // let the screen reader user know to use arrow keys
1020
+ opts.field.setAttribute('aria-label', 'Use the arrow keys to pick a date');
1021
+ }
1022
+ },
1023
+
1024
+ adjustPosition: function()
1025
+ {
1026
+ var field, pEl, width, height, viewportWidth, viewportHeight, scrollTop, left, top, clientRect;
1027
+
1028
+ if (this._o.container) return;
1029
+
1030
+ this.el.style.position = 'absolute';
1031
+
1032
+ field = this._o.trigger;
1033
+ pEl = field;
1034
+ width = this.el.offsetWidth;
1035
+ height = this.el.offsetHeight;
1036
+ viewportWidth = window.innerWidth || document.documentElement.clientWidth;
1037
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight;
1038
+ scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop;
1039
+
1040
+ if (typeof field.getBoundingClientRect === 'function') {
1041
+ clientRect = field.getBoundingClientRect();
1042
+ left = clientRect.left + window.pageXOffset;
1043
+ top = clientRect.bottom + window.pageYOffset;
1044
+ } else {
1045
+ left = pEl.offsetLeft;
1046
+ top = pEl.offsetTop + pEl.offsetHeight;
1047
+ while((pEl = pEl.offsetParent)) {
1048
+ left += pEl.offsetLeft;
1049
+ top += pEl.offsetTop;
1050
+ }
1051
+ }
1052
+
1053
+ // default position is bottom & left
1054
+ if ((this._o.reposition && left + width > viewportWidth) ||
1055
+ (
1056
+ this._o.position.indexOf('right') > -1 &&
1057
+ left - width + field.offsetWidth > 0
1058
+ )
1059
+ ) {
1060
+ left = left - width + field.offsetWidth;
1061
+ }
1062
+ if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
1063
+ (
1064
+ this._o.position.indexOf('top') > -1 &&
1065
+ top - height - field.offsetHeight > 0
1066
+ )
1067
+ ) {
1068
+ top = top - height - field.offsetHeight;
1069
+ }
1070
+
1071
+ this.el.style.left = left + 'px';
1072
+ this.el.style.top = top + 'px';
1073
+ },
1074
+
1075
+ /**
1076
+ * render HTML for a particular month
1077
+ */
1078
+ render: function(year, month, randId)
1079
+ {
1080
+ var opts = this._o,
1081
+ now = new Date(),
1082
+ days = getDaysInMonth(year, month),
1083
+ before = new Date(year, month, 1).getDay(),
1084
+ data = [],
1085
+ row = [];
1086
+ setToStartOfDay(now);
1087
+ if (opts.firstDay > 0) {
1088
+ before -= opts.firstDay;
1089
+ if (before < 0) {
1090
+ before += 7;
1091
+ }
1092
+ }
1093
+ var previousMonth = month === 0 ? 11 : month - 1,
1094
+ nextMonth = month === 11 ? 0 : month + 1,
1095
+ yearOfPreviousMonth = month === 0 ? year - 1 : year,
1096
+ yearOfNextMonth = month === 11 ? year + 1 : year,
1097
+ daysInPreviousMonth = getDaysInMonth(yearOfPreviousMonth, previousMonth);
1098
+ var cells = days + before,
1099
+ after = cells;
1100
+ while(after > 7) {
1101
+ after -= 7;
1102
+ }
1103
+ cells += 7 - after;
1104
+ var isWeekSelected = false;
1105
+ for (var i = 0, r = 0; i < cells; i++)
1106
+ {
1107
+ var day = new Date(year, month, 1 + (i - before)),
1108
+ isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
1109
+ isToday = compareDates(day, now),
1110
+ hasEvent = opts.events.indexOf(day.toDateString()) !== -1 ? true : false,
1111
+ isEmpty = i < before || i >= (days + before),
1112
+ dayNumber = 1 + (i - before),
1113
+ monthNumber = month,
1114
+ yearNumber = year,
1115
+ isStartRange = opts.startRange && compareDates(opts.startRange, day),
1116
+ isEndRange = opts.endRange && compareDates(opts.endRange, day),
1117
+ isInRange = opts.startRange && opts.endRange && opts.startRange < day && day < opts.endRange,
1118
+ isDisabled = (opts.minDate && day < opts.minDate) ||
1119
+ (opts.maxDate && day > opts.maxDate) ||
1120
+ (opts.disableWeekends && isWeekend(day)) ||
1121
+ (opts.disableDayFn && opts.disableDayFn(day));
1122
+
1123
+ if (isEmpty) {
1124
+ if (i < before) {
1125
+ dayNumber = daysInPreviousMonth + dayNumber;
1126
+ monthNumber = previousMonth;
1127
+ yearNumber = yearOfPreviousMonth;
1128
+ } else {
1129
+ dayNumber = dayNumber - days;
1130
+ monthNumber = nextMonth;
1131
+ yearNumber = yearOfNextMonth;
1132
+ }
1133
+ }
1134
+
1135
+ var dayConfig = {
1136
+ day: dayNumber,
1137
+ month: monthNumber,
1138
+ year: yearNumber,
1139
+ hasEvent: hasEvent,
1140
+ isSelected: isSelected,
1141
+ isToday: isToday,
1142
+ isDisabled: isDisabled,
1143
+ isEmpty: isEmpty,
1144
+ isStartRange: isStartRange,
1145
+ isEndRange: isEndRange,
1146
+ isInRange: isInRange,
1147
+ showDaysInNextAndPreviousMonths: opts.showDaysInNextAndPreviousMonths,
1148
+ enableSelectionDaysInNextAndPreviousMonths: opts.enableSelectionDaysInNextAndPreviousMonths
1149
+ };
1150
+
1151
+ if (opts.pickWholeWeek && isSelected) {
1152
+ isWeekSelected = true;
1153
+ }
1154
+
1155
+ row.push(renderDay(dayConfig));
1156
+
1157
+ if (++r === 7) {
1158
+ if (opts.showWeekNumber) {
1159
+ row.unshift(renderWeek(i - before, month, year));
1160
+ }
1161
+ data.push(renderRow(row, opts.isRTL, opts.pickWholeWeek, isWeekSelected));
1162
+ row = [];
1163
+ r = 0;
1164
+ isWeekSelected = false;
1165
+ }
1166
+ }
1167
+ return renderTable(opts, data, randId);
1168
+ },
1169
+
1170
+ isVisible: function()
1171
+ {
1172
+ return this._v;
1173
+ },
1174
+
1175
+ show: function()
1176
+ {
1177
+ if (!this.isVisible()) {
1178
+ this._v = true;
1179
+ this.draw();
1180
+ removeClass(this.el, 'is-hidden');
1181
+ if (this._o.bound) {
1182
+ addEvent(document, 'click', this._onClick);
1183
+ this.adjustPosition();
1184
+ }
1185
+ if (typeof this._o.onOpen === 'function') {
1186
+ this._o.onOpen.call(this);
1187
+ }
1188
+ }
1189
+ },
1190
+
1191
+ hide: function()
1192
+ {
1193
+ var v = this._v;
1194
+ if (v !== false) {
1195
+ if (this._o.bound) {
1196
+ removeEvent(document, 'click', this._onClick);
1197
+ }
1198
+ this.el.style.position = 'static'; // reset
1199
+ this.el.style.left = 'auto';
1200
+ this.el.style.top = 'auto';
1201
+ addClass(this.el, 'is-hidden');
1202
+ this._v = false;
1203
+ if (v !== undefined && typeof this._o.onClose === 'function') {
1204
+ this._o.onClose.call(this);
1205
+ }
1206
+ }
1207
+ },
1208
+
1209
+ /**
1210
+ * GAME OVER
1211
+ */
1212
+ destroy: function()
1213
+ {
1214
+ this.hide();
1215
+ removeEvent(this.el, 'mousedown', this._onMouseDown, true);
1216
+ removeEvent(this.el, 'touchend', this._onMouseDown, true);
1217
+ removeEvent(this.el, 'change', this._onChange);
1218
+ removeEvent(document, 'keydown', this._onKeyChange);
1219
+ if (this._o.field) {
1220
+ removeEvent(this._o.field, 'change', this._onInputChange);
1221
+ if (this._o.bound) {
1222
+ removeEvent(this._o.trigger, 'click', this._onInputClick);
1223
+ removeEvent(this._o.trigger, 'focus', this._onInputFocus);
1224
+ removeEvent(this._o.trigger, 'blur', this._onInputBlur);
1225
+ }
1226
+ }
1227
+ if (this.el.parentNode) {
1228
+ this.el.parentNode.removeChild(this.el);
1229
+ }
1230
+ }
1231
+
1232
+ };
1233
+
1234
+ return Pikaday;
1235
+
1236
+ }));
js/lib/pikaday.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e,t){"use strict";var n;if("object"==typeof exports){try{n=require("moment")}catch(e){}module.exports=t(n)}else"function"==typeof define&&define.amd?define(function(e){try{n=e("moment")}catch(e){}return t(n)}):e.Pikaday=t(e.moment)}(this,function(e){"use strict";var t="function"==typeof e,n=!!window.addEventListener,a=window.document,i=window.setTimeout,s=function(e,t,a,i){n?e.addEventListener(t,a,!!i):e.attachEvent("on"+t,a)},o=function(e,t,a,i){n?e.removeEventListener(t,a,!!i):e.detachEvent("on"+t,a)},r=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")},h=function(e,t){return-1!==(" "+e.className+" ").indexOf(" "+t+" ")},l=function(e,t){h(e,t)||(e.className=""===e.className?t:e.className+" "+t)},d=function(e,t){e.className=r((" "+e.className+" ").replace(" "+t+" "," "))},u=function(e){return/Array/.test(Object.prototype.toString.call(e))},c=function(e){return/Date/.test(Object.prototype.toString.call(e))&&!isNaN(e.getTime())},f=function(e){var t=e.getDay();return 0===t||6===t},g=function(e){return e%4==0&&e%100!=0||e%400==0},m=function(e,t){return[31,g(e)?29:28,31,30,31,30,31,31,30,31,30,31][t]},p=function(e){c(e)&&e.setHours(0,0,0,0)},y=function(e,t){return e.getTime()===t.getTime()},D=function(e,t,n){var a,i;for(a in t)i=void 0!==e[a],i&&"object"==typeof t[a]&&null!==t[a]&&void 0===t[a].nodeName?c(t[a])?n&&(e[a]=new Date(t[a].getTime())):u(t[a])?n&&(e[a]=t[a].slice(0)):e[a]=D({},t[a],n):!n&&i||(e[a]=t[a]);return e},v=function(e,t,n){var i;a.createEvent?(i=a.createEvent("HTMLEvents"),i.initEvent(t,!0,!1),i=D(i,n),e.dispatchEvent(i)):a.createEventObject&&(i=a.createEventObject(),i=D(i,n),e.fireEvent("on"+t,i))},_=function(e){return e.month<0&&(e.year-=Math.ceil(Math.abs(e.month)/12),e.month+=12),e.month>11&&(e.year+=Math.floor(Math.abs(e.month)/12),e.month-=12),e},b={field:null,bound:void 0,position:"bottom left",reposition:!0,format:"YYYY-MM-DD",toString:null,parse:null,defaultDate:null,setDefaultDate:!1,firstDay:0,formatStrict:!1,minDate:null,maxDate:null,yearRange:10,showWeekNumber:!1,pickWholeWeek:!1,minYear:0,maxYear:9999,minMonth:void 0,maxMonth:void 0,startRange:null,endRange:null,isRTL:!1,yearSuffix:"",showMonthAfterYear:!1,showDaysInNextAndPreviousMonths:!1,enableSelectionDaysInNextAndPreviousMonths:!1,numberOfMonths:1,mainCalendar:"left",container:void 0,blurFieldOnSelect:!0,i18n:{previousMonth:"Previous Month",nextMonth:"Next Month",months:["January","February","March","April","May","June","July","August","September","October","November","December"],weekdays:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],weekdaysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},theme:null,events:[],onSelect:null,onOpen:null,onClose:null,onDraw:null},w=function(e,t,n){for(t+=e.firstDay;t>=7;)t-=7;return n?e.i18n.weekdaysShort[t]:e.i18n.weekdays[t]},M=function(e){var t=[],n="false";if(e.isEmpty){if(!e.showDaysInNextAndPreviousMonths)return'<td class="is-empty"></td>';t.push("is-outside-current-month"),e.enableSelectionDaysInNextAndPreviousMonths||t.push("is-selection-disabled")}return e.isDisabled&&t.push("is-disabled"),e.isToday&&t.push("is-today"),e.isSelected&&(t.push("is-selected"),n="true"),e.hasEvent&&t.push("has-event"),e.isInRange&&t.push("is-inrange"),e.isStartRange&&t.push("is-startrange"),e.isEndRange&&t.push("is-endrange"),'<td data-day="'+e.day+'" class="'+t.join(" ")+'" aria-selected="'+n+'"><button class="pika-button pika-day" type="button" data-pika-year="'+e.year+'" data-pika-month="'+e.month+'" data-pika-day="'+e.day+'">'+e.day+"</button></td>"},k=function(e,t,n){var a=new Date(n,0,1);return'<td class="pika-week">'+Math.ceil(((new Date(n,t,e)-a)/864e5+a.getDay()+1)/7)+"</td>"},x=function(e,t,n,a){return'<tr class="pika-row'+(n?" pick-whole-week":"")+(a?" is-selected":"")+'">'+(t?e.reverse():e).join("")+"</tr>"},R=function(e){return"<tbody>"+e.join("")+"</tbody>"},N=function(e){var t,n=[];for(e.showWeekNumber&&n.push("<th></th>"),t=0;t<7;t++)n.push('<th scope="col"><abbr title="'+w(e,t)+'">'+w(e,t,!0)+"</abbr></th>");return"<thead><tr>"+(e.isRTL?n.reverse():n).join("")+"</tr></thead>"},S=function(e,t,n,a,i,s){var o,r,h,l,d,c=e._o,f=n===c.minYear,g=n===c.maxYear,m='<div id="'+s+'" class="pika-title" role="heading" aria-live="assertive">',p=!0,y=!0;for(h=[],o=0;o<12;o++)h.push('<option value="'+(n===i?o-t:12+o-t)+'"'+(o===a?' selected="selected"':"")+(f&&o<c.minMonth||g&&o>c.maxMonth?'disabled="disabled"':"")+">"+c.i18n.months[o]+"</option>");for(l='<div class="pika-label">'+c.i18n.months[a]+'<select class="pika-select pika-select-month" tabindex="-1">'+h.join("")+"</select></div>",u(c.yearRange)?(o=c.yearRange[0],r=c.yearRange[1]+1):(o=n-c.yearRange,r=1+n+c.yearRange),h=[];o<r&&o<=c.maxYear;o++)o>=c.minYear&&h.push('<option value="'+o+'"'+(o===n?' selected="selected"':"")+">"+o+"</option>");return d='<div class="pika-label">'+n+c.yearSuffix+'<select class="pika-select pika-select-year" tabindex="-1">'+h.join("")+"</select></div>",c.showMonthAfterYear?m+=d+l:m+=l+d,f&&(0===a||c.minMonth>=a)&&(p=!1),g&&(11===a||c.maxMonth<=a)&&(y=!1),0===t&&(m+='<button class="pika-prev'+(p?"":" is-disabled")+'" type="button">'+c.i18n.previousMonth+"</button>"),t===e._o.numberOfMonths-1&&(m+='<button class="pika-next'+(y?"":" is-disabled")+'" type="button">'+c.i18n.nextMonth+"</button>"),m+="</div>"},C=function(e,t,n){return'<table cellpadding="0" cellspacing="0" class="pika-table" role="grid" aria-labelledby="'+n+'">'+N(e)+R(t)+"</table>"},I=function(o){var r=this,l=r.config(o);r._onMouseDown=function(e){if(r._v){e=e||window.event;var t=e.target||e.srcElement;if(t)if(h(t,"is-disabled")||(!h(t,"pika-button")||h(t,"is-empty")||h(t.parentNode,"is-disabled")?h(t,"pika-prev")?r.prevMonth():h(t,"pika-next")&&r.nextMonth():(r.setDate(new Date(t.getAttribute("data-pika-year"),t.getAttribute("data-pika-month"),t.getAttribute("data-pika-day"))),l.bound&&i(function(){r.hide(),l.blurFieldOnSelect&&l.field&&l.field.blur()},100))),h(t,"pika-select"))r._c=!0;else{if(!e.preventDefault)return e.returnValue=!1,!1;e.preventDefault()}}},r._onChange=function(e){e=e||window.event;var t=e.target||e.srcElement;t&&(h(t,"pika-select-month")?r.gotoMonth(t.value):h(t,"pika-select-year")&&r.gotoYear(t.value))},r._onKeyChange=function(e){if(e=e||window.event,r.isVisible())switch(e.keyCode){case 13:case 27:l.field&&l.field.blur();break;case 37:e.preventDefault(),r.adjustDate("subtract",1);break;case 38:r.adjustDate("subtract",7);break;case 39:r.adjustDate("add",1);break;case 40:r.adjustDate("add",7)}},r._onInputChange=function(n){var a;n.firedBy!==r&&(l.parse?a=l.parse(l.field.value,l.format):t?(a=e(l.field.value,l.format,l.formatStrict),a=a&&a.isValid()?a.toDate():null):a=new Date(Date.parse(l.field.value)),c(a)&&r.setDate(a),r._v||r.show())},r._onInputFocus=function(){r.show()},r._onInputClick=function(){r.show()},r._onInputBlur=function(){var e=a.activeElement;do{if(h(e,"pika-single"))return}while(e=e.parentNode);r._c||(r._b=i(function(){r.hide()},50)),r._c=!1},r._onClick=function(e){e=e||window.event;var t=e.target||e.srcElement,a=t;if(t){!n&&h(t,"pika-select")&&(t.onchange||(t.setAttribute("onchange","return;"),s(t,"change",r._onChange)));do{if(h(a,"pika-single")||a===l.trigger)return}while(a=a.parentNode);r._v&&t!==l.trigger&&a!==l.trigger&&r.hide()}},r.el=a.createElement("div"),r.el.className="pika-single"+(l.isRTL?" is-rtl":"")+(l.theme?" "+l.theme:""),s(r.el,"mousedown",r._onMouseDown,!0),s(r.el,"touchend",r._onMouseDown,!0),s(r.el,"change",r._onChange),s(a,"keydown",r._onKeyChange),l.field&&(l.container?l.container.appendChild(r.el):l.bound?a.body.appendChild(r.el):l.field.parentNode.insertBefore(r.el,l.field.nextSibling),s(l.field,"change",r._onInputChange),l.defaultDate||(t&&l.field.value?l.defaultDate=e(l.field.value,l.format).toDate():l.defaultDate=new Date(Date.parse(l.field.value)),l.setDefaultDate=!0));var d=l.defaultDate;c(d)?l.setDefaultDate?r.setDate(d,!0):r.gotoDate(d):r.gotoDate(new Date),l.bound?(this.hide(),r.el.className+=" is-bound",s(l.trigger,"click",r._onInputClick),s(l.trigger,"focus",r._onInputFocus),s(l.trigger,"blur",r._onInputBlur)):this.show()};return I.prototype={config:function(e){this._o||(this._o=D({},b,!0));var t=D(this._o,e,!0);t.isRTL=!!t.isRTL,t.field=t.field&&t.field.nodeName?t.field:null,t.theme="string"==typeof t.theme&&t.theme?t.theme:null,t.bound=!!(void 0!==t.bound?t.field&&t.bound:t.field),t.trigger=t.trigger&&t.trigger.nodeName?t.trigger:t.field,t.disableWeekends=!!t.disableWeekends,t.disableDayFn="function"==typeof t.disableDayFn?t.disableDayFn:null;var n=parseInt(t.numberOfMonths,10)||1;if(t.numberOfMonths=n>4?4:n,c(t.minDate)||(t.minDate=!1),c(t.maxDate)||(t.maxDate=!1),t.minDate&&t.maxDate&&t.maxDate<t.minDate&&(t.maxDate=t.minDate=!1),t.minDate&&this.setMinDate(t.minDate),t.maxDate&&this.setMaxDate(t.maxDate),u(t.yearRange)){var a=(new Date).getFullYear()-10;t.yearRange[0]=parseInt(t.yearRange[0],10)||a,t.yearRange[1]=parseInt(t.yearRange[1],10)||a}else t.yearRange=Math.abs(parseInt(t.yearRange,10))||b.yearRange,t.yearRange>100&&(t.yearRange=100);return t},toString:function(n){return n=n||this._o.format,c(this._d)?this._o.toString?this._o.toString(this._d,n):t?e(this._d).format(n):this._d.toDateString():""},getMoment:function(){return t?e(this._d):null},setMoment:function(n,a){t&&e.isMoment(n)&&this.setDate(n.toDate(),a)},getDate:function(){return c(this._d)?new Date(this._d.getTime()):null},setDate:function(e,t){if(!e)return this._d=null,this._o.field&&(this._o.field.value="",v(this._o.field,"change",{firedBy:this})),this.draw();if("string"==typeof e&&(e=new Date(Date.parse(e))),c(e)){var n=this._o.minDate,a=this._o.maxDate;c(n)&&e<n?e=n:c(a)&&e>a&&(e=a),this._d=new Date(e.getTime()),p(this._d),this.gotoDate(this._d),this._o.field&&(this._o.field.value=this.toString(),v(this._o.field,"change",{firedBy:this})),t||"function"!=typeof this._o.onSelect||this._o.onSelect.call(this,this.getDate())}},gotoDate:function(e){var t=!0;if(c(e)){if(this.calendars){var n=new Date(this.calendars[0].year,this.calendars[0].month,1),a=new Date(this.calendars[this.calendars.length-1].year,this.calendars[this.calendars.length-1].month,1),i=e.getTime();a.setMonth(a.getMonth()+1),a.setDate(a.getDate()-1),t=i<n.getTime()||a.getTime()<i}t&&(this.calendars=[{month:e.getMonth(),year:e.getFullYear()}],"right"===this._o.mainCalendar&&(this.calendars[0].month+=1-this._o.numberOfMonths)),this.adjustCalendars()}},adjustDate:function(e,t){var n,a=this.getDate()||new Date,i=24*parseInt(t)*60*60*1e3;"add"===e?n=new Date(a.valueOf()+i):"subtract"===e&&(n=new Date(a.valueOf()-i)),this.setDate(n)},adjustCalendars:function(){this.calendars[0]=_(this.calendars[0]);for(var e=1;e<this._o.numberOfMonths;e++)this.calendars[e]=_({month:this.calendars[0].month+e,year:this.calendars[0].year});this.draw()},gotoToday:function(){this.gotoDate(new Date)},gotoMonth:function(e){isNaN(e)||(this.calendars[0].month=parseInt(e,10),this.adjustCalendars())},nextMonth:function(){this.calendars[0].month++,this.adjustCalendars()},prevMonth:function(){this.calendars[0].month--,this.adjustCalendars()},gotoYear:function(e){isNaN(e)||(this.calendars[0].year=parseInt(e,10),this.adjustCalendars())},setMinDate:function(e){e instanceof Date?(p(e),this._o.minDate=e,this._o.minYear=e.getFullYear(),this._o.minMonth=e.getMonth()):(this._o.minDate=b.minDate,this._o.minYear=b.minYear,this._o.minMonth=b.minMonth,this._o.startRange=b.startRange),this.draw()},setMaxDate:function(e){e instanceof Date?(p(e),this._o.maxDate=e,this._o.maxYear=e.getFullYear(),this._o.maxMonth=e.getMonth()):(this._o.maxDate=b.maxDate,this._o.maxYear=b.maxYear,this._o.maxMonth=b.maxMonth,this._o.endRange=b.endRange),this.draw()},setStartRange:function(e){this._o.startRange=e},setEndRange:function(e){this._o.endRange=e},draw:function(e){if(this._v||e){var t,n=this._o,a=n.minYear,s=n.maxYear,o=n.minMonth,r=n.maxMonth,h="";this._y<=a&&(this._y=a,!isNaN(o)&&this._m<o&&(this._m=o)),this._y>=s&&(this._y=s,!isNaN(r)&&this._m>r&&(this._m=r)),t="pika-title-"+Math.random().toString(36).replace(/[^a-z]+/g,"").substr(0,2);for(var l=0;l<n.numberOfMonths;l++)h+='<div class="pika-lendar">'+S(this,l,this.calendars[l].year,this.calendars[l].month,this.calendars[0].year,t)+this.render(this.calendars[l].year,this.calendars[l].month,t)+"</div>";this.el.innerHTML=h,n.bound&&"hidden"!==n.field.type&&i(function(){n.trigger.focus()},1),"function"==typeof this._o.onDraw&&this._o.onDraw(this),n.bound&&n.field.setAttribute("aria-label","Use the arrow keys to pick a date")}},adjustPosition:function(){var e,t,n,i,s,o,r,h,l,d;if(!this._o.container){if(this.el.style.position="absolute",e=this._o.trigger,t=e,n=this.el.offsetWidth,i=this.el.offsetHeight,s=window.innerWidth||a.documentElement.clientWidth,o=window.innerHeight||a.documentElement.clientHeight,r=window.pageYOffset||a.body.scrollTop||a.documentElement.scrollTop,"function"==typeof e.getBoundingClientRect)d=e.getBoundingClientRect(),h=d.left+window.pageXOffset,l=d.bottom+window.pageYOffset;else for(h=t.offsetLeft,l=t.offsetTop+t.offsetHeight;t=t.offsetParent;)h+=t.offsetLeft,l+=t.offsetTop;(this._o.reposition&&h+n>s||this._o.position.indexOf("right")>-1&&h-n+e.offsetWidth>0)&&(h=h-n+e.offsetWidth),(this._o.reposition&&l+i>o+r||this._o.position.indexOf("top")>-1&&l-i-e.offsetHeight>0)&&(l=l-i-e.offsetHeight),this.el.style.left=h+"px",this.el.style.top=l+"px"}},render:function(e,t,n){var a=this._o,i=new Date,s=m(e,t),o=new Date(e,t,1).getDay(),r=[],h=[];p(i),a.firstDay>0&&(o-=a.firstDay)<0&&(o+=7);for(var l=0===t?11:t-1,d=11===t?0:t+1,u=0===t?e-1:e,g=11===t?e+1:e,D=m(u,l),v=s+o,_=v;_>7;)_-=7;v+=7-_;for(var b=!1,w=0,R=0;w<v;w++){var N=new Date(e,t,w-o+1),S=!!c(this._d)&&y(N,this._d),I=y(N,i),T=-1!==a.events.indexOf(N.toDateString()),E=w<o||w>=s+o,Y=w-o+1,O=t,j=e,W=a.startRange&&y(a.startRange,N),A=a.endRange&&y(a.endRange,N),F=a.startRange&&a.endRange&&a.startRange<N&&N<a.endRange,L=a.minDate&&N<a.minDate||a.maxDate&&N>a.maxDate||a.disableWeekends&&f(N)||a.disableDayFn&&a.disableDayFn(N);E&&(w<o?(Y=D+Y,O=l,j=u):(Y-=s,O=d,j=g));var P={day:Y,month:O,year:j,hasEvent:T,isSelected:S,isToday:I,isDisabled:L,isEmpty:E,isStartRange:W,isEndRange:A,isInRange:F,showDaysInNextAndPreviousMonths:a.showDaysInNextAndPreviousMonths,enableSelectionDaysInNextAndPreviousMonths:a.enableSelectionDaysInNextAndPreviousMonths};a.pickWholeWeek&&S&&(b=!0),h.push(M(P)),7==++R&&(a.showWeekNumber&&h.unshift(k(w-o,t,e)),r.push(x(h,a.isRTL,a.pickWholeWeek,b)),h=[],R=0,b=!1)}return C(a,r,n)},isVisible:function(){return this._v},show:function(){this.isVisible()||(this._v=!0,this.draw(),d(this.el,"is-hidden"),this._o.bound&&(s(a,"click",this._onClick),this.adjustPosition()),"function"==typeof this._o.onOpen&&this._o.onOpen.call(this))},hide:function(){var e=this._v;!1!==e&&(this._o.bound&&o(a,"click",this._onClick),this.el.style.position="static",this.el.style.left="auto",this.el.style.top="auto",l(this.el,"is-hidden"),this._v=!1,void 0!==e&&"function"==typeof this._o.onClose&&this._o.onClose.call(this))},destroy:function(){this.hide(),o(this.el,"mousedown",this._onMouseDown,!0),o(this.el,"touchend",this._onMouseDown,!0),o(this.el,"change",this._onChange),o(a,"keydown",this._onKeyChange),this._o.field&&(o(this._o.field,"change",this._onInputChange),this._o.bound&&(o(this._o.trigger,"click",this._onInputClick),o(this._o.trigger,"focus",this._onInputFocus),o(this._o.trigger,"blur",this._onInputBlur))),this.el.parentNode&&this.el.parentNode.removeChild(this.el)}},I});
js/sow.google.map.js CHANGED
@@ -28,7 +28,11 @@ sowb.SiteOriginGoogleMap = function($) {
28
  panControl: options.panControl,
29
  center: location,
30
  mapTypeControlOptions: {
31
- mapTypeIds: [google.maps.MapTypeId.ROADMAP, userMapTypeId]
 
 
 
 
32
  }
33
  };
34
 
28
  panControl: options.panControl,
29
  center: location,
30
  mapTypeControlOptions: {
31
+ mapTypeIds: [
32
+ google.maps.MapTypeId.ROADMAP,
33
+ google.maps.MapTypeId.SATELLITE,
34
+ userMapTypeId
35
+ ]
36
  }
37
  };
38
 
js/sow.google.map.min.js CHANGED
@@ -1 +1 @@
1
- function soGoogleMapInitialize(){new sowb.SiteOriginGoogleMap(jQuery).initMaps()}var sowb=window.sowb||{};sowb.SiteOriginGoogleMap=function(e){return{DEFAULT_LOCATIONS:["Addo Elephant National Park, R335, Addo","Cape Town, Western Cape, South Africa","San Francisco Bay Area, CA, United States","New York, NY, United States"],showMap:function(o,t,i){var n=Number(i.zoom);n||(n=14);var a={zoom:n,scrollwheel:i.scrollZoom,draggable:i.draggable,disableDefaultUI:i.disableUi,zoomControl:i.zoomControl,panControl:i.panControl,center:t,mapTypeControlOptions:{mapTypeIds:[google.maps.MapTypeId.ROADMAP,"user_map_style"]}},s=new google.maps.Map(o,a),r={name:i.mapName},l=i.mapStyles;if(l){var d=new google.maps.StyledMapType(l,r);s.mapTypes.set("user_map_style",d),s.setMapTypeId("user_map_style")}if(i.markerAtCenter&&(this.centerMarker=new google.maps.Marker({position:t,map:s,draggable:i.markersDraggable,icon:i.markerIcon,title:""})),i.keepCentered){var c;google.maps.event.addDomListener(s,"idle",function(){c=s.getCenter()}),google.maps.event.addDomListener(window,"resize",function(){s.setCenter(c)})}if(this.linkAutocompleteField(i.autocomplete,i.autocompleteElement,s,i),this.showMarkers(i.markerPositions,s,i),this.showDirections(i.directions,s,i),e(o).is(":hidden")){e(o).closest(":visible").find("> :hidden").on("show",function(){google.maps.event.trigger(s,"resize"),s.setCenter(t)})}},linkAutocompleteField:function(o,t,i,n){if(o&&t){var a=function(e){this.inputAddress!==e&&(this.inputAddress=e,this.getLocation(this.inputAddress).done(function(e){i.setZoom(15),i.setCenter(e),this.centerMarker&&(this.centerMarker.setPosition(e),this.centerMarker.setTitle(this.inputAddress))}.bind(this)))}.bind(this),s=e(t);o.addListener("place_changed",function(){var e=o.getPlace();i.setZoom(15),e.geometry&&(i.setCenter(e.geometry.location),this.centerMarker&&this.centerMarker.setPosition(e.geometry.location))}.bind(this)),google.maps.event.addDomListener(t,"keypress",function(e){"13"===(e.keyCode||e.which)&&e.preventDefault()}),s.focusin(function(){if(!this.resultsObserver){var o=document.querySelector(".pac-container");this.resultsObserver=new MutationObserver(function(){var o=e(e(".pac-item").get(0)),t=o.find(".pac-item-query").text(),i=o.find("span").not("[class]").text(),n=t+(i?", "+i:"");n&&a(n)});var t={attributes:!0,childList:!0,characterData:!0};this.resultsObserver.observe(o,t)}}.bind(this));var r=function(e){this.getGeocoder().geocode({location:e},function(o,t){if(t===google.maps.GeocoderStatus.OK&&o.length>0){var i=o[0].formatted_address;s.val(i),this.centerMarker&&(this.centerMarker.setPosition(e),this.centerMarker.setTitle(i))}}.bind(this))}.bind(this);i.addListener("click",function(e){r(e.latLng)}),this.centerMarker.addListener("dragend",function(e){r(e.latLng)})}},showMarkers:function(e,o,t){if(e&&e.length){this.infoWindows=[];for(var i=[],n=0;n<e.length;n++){var a=parseInt(n/10);i.length===a&&(i[a]=[]),i[a][n%10]=e[n]}var s=function(e,i){var n=0;e.forEach(function(a){this.getLocation(a.place).done(function(r){var l=t.markerIcon;a.custom_marker_icon&&(l=a.custom_marker_icon);var d=new google.maps.Marker({position:r,map:o,draggable:t.markersDraggable,icon:l,title:""});if(a.hasOwnProperty("info")&&a.info){var c={content:a.info};a.hasOwnProperty("info_max_width")&&a.info_max_width&&(c.maxWidth=a.info_max_width);var p=t.markerInfoDisplay;c.disableAutoPan="always"===p;var g=new google.maps.InfoWindow(c);this.infoWindows.push(g);var h=p;"always"===p&&(h="click",g.open(o,d)),d.addListener(h,function(){g.open(o,d),"always"===p||t.markerInfoMultiple||this.infoWindows.forEach(function(e){e!==g&&e.close()})}.bind(this)),"mouseover"===p&&d.addListener("mouseout",function(){setTimeout(function(){g.close()},100)})}++n===e.length&&i.length&&s(i.shift(),i)}.bind(this))}.bind(this))}.bind(this);s(i.shift(),i)}},showDirections:function(e,o){if(e){e.waypoints&&e.waypoints.length&&e.waypoints.map(function(e){e.stopover=Boolean(e.stopover)});var t=new google.maps.DirectionsRenderer;t.setMap(o);(new google.maps.DirectionsService).route({origin:e.origin,destination:e.destination,travelMode:e.travelMode.toUpperCase(),avoidHighways:e.avoidHighways,avoidTolls:e.avoidTolls,waypoints:e.waypoints,optimizeWaypoints:e.optimizeWaypoints},function(o,i){i===google.maps.DirectionsStatus.OK&&(t.setOptions({preserveViewport:e.preserveViewport}),t.setDirections(o))})}},initMaps:function(){var o=e(".sow-google-map-autocomplete"),t=new e.Deferred;0===o.length?t.resolve():o.each(function(o,i){if(void 0===google.maps.places)return void t.reject('Sorry, we couldn\'t load the "places" library due to another plugin, so the autocomplete feature is not available.');var n=new google.maps.places.Autocomplete(i,{types:["address"]}),a=e(i).siblings(".sow-google-map-canvas");if(a.length>0){var s=a.data("options");s.autocomplete=n,s.autocompleteElement=i,this.getLocation(s.address).done(function(e){this.showMap(a.get(0),e,s),a.data("initialized",!0),t.resolve()}.bind(this)).fail(function(){a.append("<div><p><strong>"+soWidgetsGoogleMap.geocode.noResults+"</strong></p></div>"),t.reject()})}}.bind(this)),t.always(function(){e(".sow-google-map-canvas").each(function(o,t){var i=e(t);if(i.data("initialized"))return!0;var n=i.data("options"),a=n.address;if(!a){var s=n.markerPositions;s&&s.length&&(a=s[0].place)}this.getLocation(a).done(function(e){this.showMap(i.get(0),e,n),i.data("initialized")}.bind(this)).fail(function(){i.append("<div><p><strong>"+soWidgetsGoogleMap.geocode.noResults+"</strong></p></div>")})}.bind(this))}.bind(this)).fail(function(e){console.log(e)})},getGeocoder:function(){return this._geocoder||(this._geocoder=new google.maps.Geocoder),this._geocoder},getLocation:function(o){var t,i=new e.Deferred,n={address:o};if(o&&o.indexOf(",")>-1){var a=o.split(",");a&&2===a.length&&(t=new google.maps.LatLng(a[0],a[1]),isNaN(t.lat())||isNaN(t.lng())||(n={location:{lat:t.lat(),lng:t.lng()}}))}if(n.hasOwnProperty("location"))i.resolve(n.location);else if(n.hasOwnProperty("address")){if(!n.address){var s=parseInt(Math.random()*this.DEFAULT_LOCATIONS.length);n.address=this.DEFAULT_LOCATIONS[s]}var r=function(e,o){o===google.maps.GeocoderStatus.OK?i.resolve(e[0].geometry.location):o===google.maps.GeocoderStatus.OVER_QUERY_LIMIT?setTimeout(function(){this.getGeocoder().geocode.call(this,n,r)}.bind(this),100):o===google.maps.GeocoderStatus.ZERO_RESULTS&&i.reject(o)}.bind(this);this.getGeocoder().geocode(n,r)}return i}}},jQuery(function(e){sowb.setupGoogleMaps=function(){var o,t=[];if(e(".sow-google-map-canvas").each(function(i,n){var a=e(n),s=a.data("options");s&&(void 0!==s.libraries&&null!==s.libraries&&(t=t.concat(s.libraries)),!o&&s.apiKey&&(o=s.apiKey))}),void 0!==window.google&&void 0!==window.google.maps)soGoogleMapInitialize();else{var i="https://maps.googleapis.com/maps/api/js?callback=soGoogleMapInitialize";if(t&&t.length&&(i+="&libraries="+t.join(",")),o&&(i+="&key="+o),window.console&&window.console.error){var n=window.console.error;sowb.onLoadMapsApiError=function(o){var t=o.match(/^Google Maps API (error|warning): ([^\s]*)\s([^\s]*)(?:\s(.*))?/);t&&t.length&&t[0]&&e(".sow-google-map-canvas").each(function(o,t){var i=e(t);if(i.data("fallbackImage")){var n=i.data("fallbackImage");n.hasOwnProperty("img")&&i.append(n.img)}}),n.apply(window.console,arguments)},window.console.error=sowb.onLoadMapsApiError}e("body").append('<script async type="text/javascript" src="'+i+'">')}},sowb.setupGoogleMaps(),e(sowb).on("setup_widgets",sowb.setupGoogleMaps)}),window.sowb=sowb;
1
+ function soGoogleMapInitialize(){new sowb.SiteOriginGoogleMap(jQuery).initMaps()}var sowb=window.sowb||{};sowb.SiteOriginGoogleMap=function(e){return{DEFAULT_LOCATIONS:["Addo Elephant National Park, R335, Addo","Cape Town, Western Cape, South Africa","San Francisco Bay Area, CA, United States","New York, NY, United States"],showMap:function(o,t,i){var n=Number(i.zoom);n||(n=14);var a={zoom:n,scrollwheel:i.scrollZoom,draggable:i.draggable,disableDefaultUI:i.disableUi,zoomControl:i.zoomControl,panControl:i.panControl,center:t,mapTypeControlOptions:{mapTypeIds:[google.maps.MapTypeId.ROADMAP,google.maps.MapTypeId.SATELLITE,"user_map_style"]}},s=new google.maps.Map(o,a),r={name:i.mapName},l=i.mapStyles;if(l){var d=new google.maps.StyledMapType(l,r);s.mapTypes.set("user_map_style",d),s.setMapTypeId("user_map_style")}if(i.markerAtCenter&&(this.centerMarker=new google.maps.Marker({position:t,map:s,draggable:i.markersDraggable,icon:i.markerIcon,title:""})),i.keepCentered){var c;google.maps.event.addDomListener(s,"idle",function(){c=s.getCenter()}),google.maps.event.addDomListener(window,"resize",function(){s.setCenter(c)})}if(this.linkAutocompleteField(i.autocomplete,i.autocompleteElement,s,i),this.showMarkers(i.markerPositions,s,i),this.showDirections(i.directions,s,i),e(o).is(":hidden")){e(o).closest(":visible").find("> :hidden").on("show",function(){google.maps.event.trigger(s,"resize"),s.setCenter(t)})}},linkAutocompleteField:function(o,t,i,n){if(o&&t){var a=function(e){this.inputAddress!==e&&(this.inputAddress=e,this.getLocation(this.inputAddress).done(function(e){i.setZoom(15),i.setCenter(e),this.centerMarker&&(this.centerMarker.setPosition(e),this.centerMarker.setTitle(this.inputAddress))}.bind(this)))}.bind(this),s=e(t);o.addListener("place_changed",function(){var e=o.getPlace();i.setZoom(15),e.geometry&&(i.setCenter(e.geometry.location),this.centerMarker&&this.centerMarker.setPosition(e.geometry.location))}.bind(this)),google.maps.event.addDomListener(t,"keypress",function(e){"13"===(e.keyCode||e.which)&&e.preventDefault()}),s.focusin(function(){if(!this.resultsObserver){var o=document.querySelector(".pac-container");this.resultsObserver=new MutationObserver(function(){var o=e(e(".pac-item").get(0)),t=o.find(".pac-item-query").text(),i=o.find("span").not("[class]").text(),n=t+(i?", "+i:"");n&&a(n)});var t={attributes:!0,childList:!0,characterData:!0};this.resultsObserver.observe(o,t)}}.bind(this));var r=function(e){this.getGeocoder().geocode({location:e},function(o,t){if(t===google.maps.GeocoderStatus.OK&&o.length>0){var i=o[0].formatted_address;s.val(i),this.centerMarker&&(this.centerMarker.setPosition(e),this.centerMarker.setTitle(i))}}.bind(this))}.bind(this);i.addListener("click",function(e){r(e.latLng)}),this.centerMarker.addListener("dragend",function(e){r(e.latLng)})}},showMarkers:function(e,o,t){if(e&&e.length){this.infoWindows=[];for(var i=[],n=0;n<e.length;n++){var a=parseInt(n/10);i.length===a&&(i[a]=[]),i[a][n%10]=e[n]}var s=function(e,i){var n=0;e.forEach(function(a){this.getLocation(a.place).done(function(r){var l=t.markerIcon;a.custom_marker_icon&&(l=a.custom_marker_icon);var d=new google.maps.Marker({position:r,map:o,draggable:t.markersDraggable,icon:l,title:""});if(a.hasOwnProperty("info")&&a.info){var c={content:a.info};a.hasOwnProperty("info_max_width")&&a.info_max_width&&(c.maxWidth=a.info_max_width);var p=t.markerInfoDisplay;c.disableAutoPan="always"===p;var g=new google.maps.InfoWindow(c);this.infoWindows.push(g);var h=p;"always"===p&&(h="click",g.open(o,d)),d.addListener(h,function(){g.open(o,d),"always"===p||t.markerInfoMultiple||this.infoWindows.forEach(function(e){e!==g&&e.close()})}.bind(this)),"mouseover"===p&&d.addListener("mouseout",function(){setTimeout(function(){g.close()},100)})}++n===e.length&&i.length&&s(i.shift(),i)}.bind(this))}.bind(this))}.bind(this);s(i.shift(),i)}},showDirections:function(e,o){if(e){e.waypoints&&e.waypoints.length&&e.waypoints.map(function(e){e.stopover=Boolean(e.stopover)});var t=new google.maps.DirectionsRenderer;t.setMap(o);(new google.maps.DirectionsService).route({origin:e.origin,destination:e.destination,travelMode:e.travelMode.toUpperCase(),avoidHighways:e.avoidHighways,avoidTolls:e.avoidTolls,waypoints:e.waypoints,optimizeWaypoints:e.optimizeWaypoints},function(o,i){i===google.maps.DirectionsStatus.OK&&(t.setOptions({preserveViewport:e.preserveViewport}),t.setDirections(o))})}},initMaps:function(){var o=e(".sow-google-map-autocomplete"),t=new e.Deferred;0===o.length?t.resolve():o.each(function(o,i){if(void 0===google.maps.places)return void t.reject('Sorry, we couldn\'t load the "places" library due to another plugin, so the autocomplete feature is not available.');var n=new google.maps.places.Autocomplete(i,{types:["address"]}),a=e(i).siblings(".sow-google-map-canvas");if(a.length>0){var s=a.data("options");s.autocomplete=n,s.autocompleteElement=i,this.getLocation(s.address).done(function(e){this.showMap(a.get(0),e,s),a.data("initialized",!0),t.resolve()}.bind(this)).fail(function(){a.append("<div><p><strong>"+soWidgetsGoogleMap.geocode.noResults+"</strong></p></div>"),t.reject()})}}.bind(this)),t.always(function(){e(".sow-google-map-canvas").each(function(o,t){var i=e(t);if(i.data("initialized"))return!0;var n=i.data("options"),a=n.address;if(!a){var s=n.markerPositions;s&&s.length&&(a=s[0].place)}this.getLocation(a).done(function(e){this.showMap(i.get(0),e,n),i.data("initialized")}.bind(this)).fail(function(){i.append("<div><p><strong>"+soWidgetsGoogleMap.geocode.noResults+"</strong></p></div>")})}.bind(this))}.bind(this)).fail(function(e){console.log(e)})},getGeocoder:function(){return this._geocoder||(this._geocoder=new google.maps.Geocoder),this._geocoder},getLocation:function(o){var t,i=new e.Deferred,n={address:o};if(o&&o.indexOf(",")>-1){var a=o.split(",");a&&2===a.length&&(t=new google.maps.LatLng(a[0],a[1]),isNaN(t.lat())||isNaN(t.lng())||(n={location:{lat:t.lat(),lng:t.lng()}}))}if(n.hasOwnProperty("location"))i.resolve(n.location);else if(n.hasOwnProperty("address")){if(!n.address){var s=parseInt(Math.random()*this.DEFAULT_LOCATIONS.length);n.address=this.DEFAULT_LOCATIONS[s]}var r=function(e,o){o===google.maps.GeocoderStatus.OK?i.resolve(e[0].geometry.location):o===google.maps.GeocoderStatus.OVER_QUERY_LIMIT?setTimeout(function(){this.getGeocoder().geocode.call(this,n,r)}.bind(this),100):o===google.maps.GeocoderStatus.ZERO_RESULTS&&i.reject(o)}.bind(this);this.getGeocoder().geocode(n,r)}return i}}},jQuery(function(e){sowb.setupGoogleMaps=function(){var o,t=[];if(e(".sow-google-map-canvas").each(function(i,n){var a=e(n),s=a.data("options");s&&(void 0!==s.libraries&&null!==s.libraries&&(t=t.concat(s.libraries)),!o&&s.apiKey&&(o=s.apiKey))}),void 0!==window.google&&void 0!==window.google.maps)soGoogleMapInitialize();else{var i="https://maps.googleapis.com/maps/api/js?callback=soGoogleMapInitialize";if(t&&t.length&&(i+="&libraries="+t.join(",")),o&&(i+="&key="+o),window.console&&window.console.error){var n=window.console.error;sowb.onLoadMapsApiError=function(o){var t=o.match(/^Google Maps API (error|warning): ([^\s]*)\s([^\s]*)(?:\s(.*))?/);t&&t.length&&t[0]&&e(".sow-google-map-canvas").each(function(o,t){var i=e(t);if(i.data("fallbackImage")){var n=i.data("fallbackImage");n.hasOwnProperty("img")&&i.append(n.img)}}),n.apply(window.console,arguments)},window.console.error=sowb.onLoadMapsApiError}e("body").append('<script async type="text/javascript" src="'+i+'">')}},sowb.setupGoogleMaps(),e(sowb).on("setup_widgets",sowb.setupGoogleMaps)}),window.sowb=sowb;
lang/so-widgets-bundle.pot CHANGED
@@ -17,7 +17,7 @@ msgstr ""
17
  "X-Poedit-SearchPathExcluded-0: *.js\n"
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
 
20
- #: tmp/admin/tpl/admin.php:17, tmp/so-widgets-bundle.php:397
21
  msgid "SiteOrigin Widgets Bundle"
22
  msgstr ""
23
 
@@ -69,27 +69,27 @@ msgstr ""
69
  msgid "Save"
70
  msgstr ""
71
 
72
- #: tmp/base/inc/actions.php:10, tmp/base/inc/actions.php:73, tmp/base/inc/actions.php:117, tmp/base/inc/actions.php:153, tmp/base/inc/actions.php:166, tmp/base/inc/actions.php:170, tmp/base/inc/actions.php:261, tmp/base/inc/actions.php:264, tmp/so-widgets-bundle.php:705, tmp/so-widgets-bundle.php:753, tmp/so-widgets-bundle.php:779, tmp/so-widgets-bundle.php:839, tmp/so-widgets-bundle.php:861, tmp/so-widgets-bundle.php:993, tmp/so-widgets-bundle.php:1015
73
  msgid "Invalid request."
74
  msgstr ""
75
 
76
- #: tmp/base/inc/actions.php:12, tmp/base/inc/actions.php:20, tmp/so-widgets-bundle.php:719, tmp/so-widgets-bundle.php:1005
77
  msgid "Invalid post."
78
  msgstr ""
79
 
80
- #: tmp/base/inc/actions.php:48, tmp/base/siteorigin-widget.class.php:635
81
  msgid "Widget Preview"
82
  msgstr ""
83
 
84
- #: tmp/base/inc/actions.php:209
85
  msgid "Nonce error"
86
  msgstr ""
87
 
88
- #: tmp/base/inc/actions.php:219
89
  msgid "Signature error"
90
  msgstr ""
91
 
92
- #: tmp/base/inc/actions.php:245
93
  msgid "Attachment error"
94
  msgstr ""
95
 
@@ -117,31 +117,36 @@ msgstr ""
117
  msgid "SiteOrigin Page Builder"
118
  msgstr ""
119
 
120
- #: tmp/base/inc/fields/date-range.class.php:31, tmp/base/inc/fields/date-range.class.php:45, tmp/widgets/contact/contact.php:2375
 
121
  msgid "From"
122
  msgstr ""
123
 
124
- #: tmp/base/inc/fields/date-range.class.php:34, tmp/base/inc/fields/date-range.class.php:48
125
  msgid "to"
126
  msgstr ""
127
 
128
- #: tmp/base/inc/fields/date-range.class.php:64
 
 
 
 
129
  msgid "ago"
130
  msgstr ""
131
 
132
- #: tmp/base/inc/fields/date-range.class.php:69
133
  msgid "days"
134
  msgstr ""
135
 
136
- #: tmp/base/inc/fields/date-range.class.php:70
137
  msgid "weeks"
138
  msgstr ""
139
 
140
- #: tmp/base/inc/fields/date-range.class.php:71
141
  msgid "months"
142
  msgstr ""
143
 
144
- #: tmp/base/inc/fields/date-range.class.php:72
145
  msgid "years"
146
  msgstr ""
147
 
@@ -297,7 +302,7 @@ msgstr ""
297
  msgid "Author"
298
  msgstr ""
299
 
300
- #: tmp/base/inc/fields/posts.class.php:82, tmp/widgets/accordion/accordion.php:46, tmp/widgets/accordion/accordion.php:59, tmp/widgets/contact/contact.php:93, tmp/widgets/cta/cta.php:125, tmp/widgets/editor/editor.php:32, tmp/widgets/features/features.php:263, tmp/widgets/post-carousel/post-carousel.php:97, tmp/widgets/price-table/price-table.php:41, tmp/widgets/price-table/price-table.php:60, tmp/widgets/simple-masonry/simple-masonry.php:43, tmp/widgets/simple-masonry/simple-masonry.php:74, tmp/widgets/social-media-buttons/social-media-buttons.php:105, tmp/widgets/tabs/tabs.php:46, tmp/widgets/tabs/tabs.php:59, tmp/widgets/taxonomy/taxonomy.php:33, tmp/widgets/testimonial/testimonial.php:79, tmp/widgets/video/video.php:32
301
  msgid "Title"
302
  msgstr ""
303
 
@@ -357,7 +362,7 @@ msgstr ""
357
  msgid "Sticky posts"
358
  msgstr ""
359
 
360
- #: tmp/base/inc/fields/posts.class.php:115, tmp/compat/beaver-builder/beaver-builder.php:129, tmp/widgets/google-map/google-map.php:537, tmp/widgets/image/image.php:46
361
  msgid "Default"
362
  msgstr ""
363
 
@@ -501,39 +506,51 @@ msgstr ""
501
  msgid "Maximum height"
502
  msgstr ""
503
 
504
- #: tmp/base/siteorigin-widget.class.php:479
 
 
 
 
 
 
 
 
 
 
 
 
505
  msgid "Preview"
506
  msgstr ""
507
 
508
- #: tmp/base/siteorigin-widget.class.php:484
509
  msgid "Help"
510
  msgstr ""
511
 
512
- #: tmp/base/siteorigin-widget.class.php:550
513
  msgid "This widget has scripts and styles that need to be loaded before you can use it. Please save and reload your current page."
514
  msgstr ""
515
 
516
- #: tmp/base/siteorigin-widget.class.php:551
517
  msgid "You will only need to do this once."
518
  msgstr ""
519
 
520
- #: tmp/base/siteorigin-widget.class.php:578
521
  msgid "Are you sure?"
522
  msgstr ""
523
 
524
- #: tmp/base/siteorigin-widget.class.php:580
525
  msgid "There is a newer version of this widget's content available."
526
  msgstr ""
527
 
528
- #: tmp/base/siteorigin-widget.class.php:581, tmp/base/siteorigin-widget.class.php:585
529
  msgid "Restore"
530
  msgstr ""
531
 
532
- #: tmp/base/siteorigin-widget.class.php:582
533
  msgid "Dismiss"
534
  msgstr ""
535
 
536
- #: tmp/base/siteorigin-widget.class.php:584
537
  msgid "Clicking %s will replace the current widget contents. You can revert by refreshing the page before updating."
538
  msgstr ""
539
 
@@ -565,7 +582,7 @@ msgstr ""
565
  msgid "SiteOrigin Widget"
566
  msgstr ""
567
 
568
- #: tmp/compat/visual-composer/visual-composer.php:40, tmp/so-widgets-bundle.php:893, tmp/so-widgets-bundle.php:895
569
  msgid "SiteOrigin Widgets"
570
  msgstr ""
571
 
@@ -601,31 +618,31 @@ msgstr ""
601
  msgid "Ionicons"
602
  msgstr ""
603
 
604
- #: tmp/so-widgets-bundle.php:429
605
  msgid "A new widget!"
606
  msgstr ""
607
 
608
- #: tmp/so-widgets-bundle.php:713, tmp/so-widgets-bundle.php:759, tmp/so-widgets-bundle.php:845
609
  msgid "Insufficient permissions."
610
  msgstr ""
611
 
612
- #: tmp/so-widgets-bundle.php:945
613
  msgid "%s was %s"
614
  msgstr ""
615
 
616
- #: tmp/so-widgets-bundle.php:949
617
  msgid "Activated"
618
  msgstr ""
619
 
620
- #: tmp/so-widgets-bundle.php:949
621
  msgid "Deactivated"
622
  msgstr ""
623
 
624
- #: tmp/so-widgets-bundle.php:1457
625
  msgid "Manage Widgets"
626
  msgstr ""
627
 
628
- #: tmp/so-widgets-bundle.php:1459
629
  msgid "Support"
630
  msgstr ""
631
 
@@ -661,7 +678,7 @@ msgstr ""
661
  msgid "Closed"
662
  msgstr ""
663
 
664
- #: tmp/widgets/accordion/accordion.php:79, tmp/widgets/contact/contact.php:571, tmp/widgets/cta/cta.php:145, tmp/widgets/tabs/tabs.php:75, tmp/widgets/testimonial/testimonial.php:363
665
  msgid "Design"
666
  msgstr ""
667
 
@@ -669,7 +686,7 @@ msgstr ""
669
  msgid "Headings"
670
  msgstr ""
671
 
672
- #: tmp/widgets/accordion/accordion.php:89, tmp/widgets/accordion/accordion.php:127, tmp/widgets/contact/contact.php:591, tmp/widgets/contact/contact.php:1049, tmp/widgets/cta/cta.php:153, tmp/widgets/hero/hero.php:235, tmp/widgets/layout-slider/layout-slider.php:81, tmp/widgets/social-media-buttons/social-media-buttons.php:169, tmp/widgets/tabs/tabs.php:85, tmp/widgets/tabs/tabs.php:105, tmp/widgets/tabs/tabs.php:149
673
  msgid "Background color"
674
  msgstr ""
675
 
@@ -685,7 +702,7 @@ msgstr ""
685
  msgid "Title hover color"
686
  msgstr ""
687
 
688
- #: tmp/widgets/accordion/accordion.php:108, tmp/widgets/accordion/accordion.php:136, tmp/widgets/contact/contact.php:611, tmp/widgets/contact/contact.php:837, tmp/widgets/contact/contact.php:1069, tmp/widgets/cta/cta.php:161, tmp/widgets/tabs/tabs.php:90, tmp/widgets/tabs/tabs.php:124, tmp/widgets/tabs/tabs.php:158
689
  msgid "Border color"
690
  msgstr ""
691
 
@@ -693,7 +710,7 @@ msgstr ""
693
  msgid "Border hover color"
694
  msgstr ""
695
 
696
- #: tmp/widgets/accordion/accordion.php:116, tmp/widgets/accordion/accordion.php:140, tmp/widgets/contact/contact.php:621, tmp/widgets/contact/contact.php:847, tmp/widgets/contact/contact.php:1101, tmp/widgets/tabs/tabs.php:94, tmp/widgets/tabs/tabs.php:134, tmp/widgets/tabs/tabs.php:162
697
  msgid "Border width"
698
  msgstr ""
699
 
@@ -721,11 +738,11 @@ msgstr ""
721
  msgid "Button text"
722
  msgstr ""
723
 
724
- #: tmp/widgets/button/button.php:99, tmp/widgets/google-map/google-map.php:193, tmp/widgets/headline/headline.php:44, tmp/widgets/headline/headline.php:115, tmp/widgets/hero/hero.php:247, tmp/widgets/icon/icon.php:56, tmp/widgets/image/image.php:76, tmp/widgets/layout-slider/layout-slider.php:87, tmp/widgets/simple-masonry/simple-masonry.php:78, tmp/widgets/slider/slider.php:84
725
  msgid "Destination URL"
726
  msgstr ""
727
 
728
- #: tmp/widgets/button/button.php:111, tmp/widgets/google-map/google-map.php:215, tmp/widgets/headline/headline.php:49, tmp/widgets/headline/headline.php:120, tmp/widgets/icon/icon.php:62, tmp/widgets/simple-masonry/simple-masonry.php:83, tmp/widgets/social-media-buttons/social-media-buttons.php:191, tmp/widgets/taxonomy/taxonomy.php:64
729
  msgid "Open in a new window"
730
  msgstr ""
731
 
@@ -753,7 +770,7 @@ msgstr ""
753
  msgid "Top"
754
  msgstr ""
755
 
756
- #: tmp/widgets/button/button.php:169, tmp/widgets/button/button.php:221, tmp/widgets/contact/contact.php:721, tmp/widgets/contact/contact.php:751, tmp/widgets/contact/contact.php:1191, tmp/widgets/cta/cta.php:193, tmp/widgets/features/features.php:127, tmp/widgets/headline/headline.php:89, tmp/widgets/headline/headline.php:160, tmp/widgets/headline/headline.php:215, tmp/widgets/icon/icon.php:49, tmp/widgets/image/image.php:48, tmp/widgets/social-media-buttons/social-media-buttons.php:303, tmp/widgets/social-media-buttons/social-media-buttons.php:325, tmp/widgets/testimonial/testimonial.php:507
757
  msgid "Right"
758
  msgstr ""
759
 
@@ -761,7 +778,7 @@ msgstr ""
761
  msgid "Bottom"
762
  msgstr ""
763
 
764
- #: tmp/widgets/button/button.php:173, tmp/widgets/button/button.php:219, tmp/widgets/contact/contact.php:719, tmp/widgets/contact/contact.php:749, tmp/widgets/contact/contact.php:1189, tmp/widgets/cta/cta.php:191, tmp/widgets/features/features.php:131, tmp/widgets/headline/headline.php:88, tmp/widgets/headline/headline.php:159, tmp/widgets/headline/headline.php:214, tmp/widgets/icon/icon.php:48, tmp/widgets/image/image.php:47, tmp/widgets/social-media-buttons/social-media-buttons.php:301, tmp/widgets/social-media-buttons/social-media-buttons.php:323, tmp/widgets/testimonial/testimonial.php:505
765
  msgid "Left"
766
  msgstr ""
767
 
@@ -769,7 +786,7 @@ msgstr ""
769
  msgid "Design and layout"
770
  msgstr ""
771
 
772
- #: tmp/widgets/button/button.php:201, tmp/widgets/contact/contact.php:733, tmp/widgets/contact/contact.php:1175, tmp/widgets/contact/contact.php:1277, tmp/widgets/google-map/google-map.php:175
773
  msgid "Width"
774
  msgstr ""
775
 
@@ -777,15 +794,15 @@ msgstr ""
777
  msgid "Leave blank to let the button resize according to content."
778
  msgstr ""
779
 
780
- #: tmp/widgets/button/button.php:213, tmp/widgets/contact/contact.php:743, tmp/widgets/contact/contact.php:1183, tmp/widgets/social-media-buttons/social-media-buttons.php:295
781
  msgid "Align"
782
  msgstr ""
783
 
784
- #: tmp/widgets/button/button.php:223, tmp/widgets/contact/contact.php:753, tmp/widgets/contact/contact.php:1193, tmp/widgets/headline/headline.php:87, tmp/widgets/headline/headline.php:158, tmp/widgets/headline/headline.php:213, tmp/widgets/icon/icon.php:47, tmp/widgets/image/image.php:49, tmp/widgets/social-media-buttons/social-media-buttons.php:305, tmp/widgets/social-media-buttons/social-media-buttons.php:327
785
  msgid "Center"
786
  msgstr ""
787
 
788
- #: tmp/widgets/button/button.php:225, tmp/widgets/contact/contact.php:755, tmp/widgets/headline/headline.php:90, tmp/widgets/headline/headline.php:161, tmp/widgets/social-media-buttons/social-media-buttons.php:307, tmp/widgets/social-media-buttons/social-media-buttons.php:329
789
  msgid "Justify"
790
  msgstr ""
791
 
@@ -809,7 +826,7 @@ msgstr ""
809
  msgid "Button color"
810
  msgstr ""
811
 
812
- #: tmp/widgets/button/button.php:271, tmp/widgets/contact/contact.php:1125, tmp/widgets/hero/hero.php:485, tmp/widgets/layout-slider/layout-slider.php:181
813
  msgid "Text color"
814
  msgstr ""
815
 
@@ -817,15 +834,15 @@ msgstr ""
817
  msgid "Use hover effects"
818
  msgstr ""
819
 
820
- #: tmp/widgets/button/button.php:293, tmp/widgets/contact/contact.php:679, tmp/widgets/contact/contact.php:779, tmp/widgets/features/features.php:273, tmp/widgets/features/features.php:315, tmp/widgets/features/features.php:357, tmp/widgets/headline/headline.php:75, tmp/widgets/headline/headline.php:146
821
  msgid "Font"
822
  msgstr ""
823
 
824
- #: tmp/widgets/button/button.php:305, tmp/widgets/contact/contact.php:689, tmp/widgets/contact/contact.php:1135
825
  msgid "Font size"
826
  msgstr ""
827
 
828
- #: tmp/widgets/button/button.php:309, tmp/widgets/contact/contact.php:505, tmp/widgets/contact/contact.php:947, tmp/widgets/contact/contact.php:1151, tmp/widgets/social-media-buttons/social-media-buttons.php:235
829
  msgid "Normal"
830
  msgstr ""
831
 
@@ -841,7 +858,7 @@ msgstr ""
841
  msgid "Rounding"
842
  msgstr ""
843
 
844
- #: tmp/widgets/button/button.php:333, tmp/widgets/contact/contact.php:637, tmp/widgets/contact/contact.php:863, tmp/widgets/contact/contact.php:1085, tmp/widgets/contact/contact.php:1255, tmp/widgets/headline/headline.php:185, tmp/widgets/social-media-buttons/social-media-buttons.php:257
845
  msgid "None"
846
  msgstr ""
847
 
@@ -857,7 +874,7 @@ msgstr ""
857
  msgid "Completely rounded"
858
  msgstr ""
859
 
860
- #: tmp/widgets/button/button.php:351, tmp/widgets/contact/contact.php:601, tmp/widgets/contact/contact.php:813, tmp/widgets/contact/contact.php:1165, tmp/widgets/social-media-buttons/social-media-buttons.php:273, tmp/widgets/testimonial/testimonial.php:465
861
  msgid "Padding"
862
  msgstr ""
863
 
@@ -1001,410 +1018,423 @@ msgstr ""
1001
  msgid "Fields marked with * are required"
1002
  msgstr ""
1003
 
1004
- #: tmp/widgets/contact/contact.php:259, tmp/widgets/contact/contact.php:771
 
 
 
 
1005
  msgid "Fields"
1006
  msgstr ""
1007
 
1008
- #: tmp/widgets/contact/contact.php:261
1009
  msgid "Field"
1010
  msgstr ""
1011
 
1012
- #: tmp/widgets/contact/contact.php:277
1013
  msgid "Field Type"
1014
  msgstr ""
1015
 
1016
- #: tmp/widgets/contact/contact.php:279
1017
  msgid "Select Field Type"
1018
  msgstr ""
1019
 
1020
- #: tmp/widgets/contact/contact.php:283, tmp/widgets/testimonial/testimonial.php:107
1021
  msgid "Name"
1022
  msgstr ""
1023
 
1024
- #: tmp/widgets/contact/contact.php:285, tmp/widgets/social-media-buttons/data/networks.php:29
1025
  msgid "Email"
1026
  msgstr ""
1027
 
1028
- #: tmp/widgets/contact/contact.php:287, tmp/widgets/contact/contact.php:1405
 
 
 
 
1029
  msgid "Subject"
1030
  msgstr ""
1031
 
1032
- #: tmp/widgets/contact/contact.php:289, tmp/widgets/features/features.php:219, tmp/widgets/features/features.php:305, tmp/widgets/headline/headline.php:40, tmp/widgets/headline/headline.php:111, tmp/widgets/price-table/price-table.php:110, tmp/widgets/taxonomy/taxonomy.php:50, tmp/widgets/testimonial/testimonial.php:161
1033
  msgid "Text"
1034
  msgstr ""
1035
 
1036
- #: tmp/widgets/contact/contact.php:291
1037
  msgid "Text Area"
1038
  msgstr ""
1039
 
1040
- #: tmp/widgets/contact/contact.php:293
1041
  msgid "Dropdown Select"
1042
  msgstr ""
1043
 
1044
- #: tmp/widgets/contact/contact.php:295
1045
  msgid "Checkboxes"
1046
  msgstr ""
1047
 
1048
- #: tmp/widgets/contact/contact.php:297
1049
  msgid "Radio"
1050
  msgstr ""
1051
 
1052
- #: tmp/widgets/contact/contact.php:317, tmp/widgets/taxonomy/taxonomy.php:42
1053
  msgid "Label"
1054
  msgstr ""
1055
 
1056
- #: tmp/widgets/contact/contact.php:327
1057
  msgid "Description"
1058
  msgstr ""
1059
 
1060
- #: tmp/widgets/contact/contact.php:329
1061
  msgid "This text will appear small beneath the input field."
1062
  msgstr ""
1063
 
1064
- #: tmp/widgets/contact/contact.php:339
1065
  msgid "Required Field"
1066
  msgstr ""
1067
 
1068
- #: tmp/widgets/contact/contact.php:347, tmp/widgets/contact/contact.php:1995
1069
  msgid "Required field"
1070
  msgstr ""
1071
 
1072
- #: tmp/widgets/contact/contact.php:349
1073
  msgid "Is this field required?"
1074
  msgstr ""
1075
 
1076
- #: tmp/widgets/contact/contact.php:357
1077
  msgid "Missing message"
1078
  msgstr ""
1079
 
1080
- #: tmp/widgets/contact/contact.php:359
1081
  msgid "Error message to display if this field is missing."
1082
  msgstr ""
1083
 
1084
- #: tmp/widgets/contact/contact.php:375
1085
  msgid "Options"
1086
  msgstr ""
1087
 
1088
- #: tmp/widgets/contact/contact.php:377
1089
  msgid "Option"
1090
  msgstr ""
1091
 
1092
- #: tmp/widgets/contact/contact.php:387
1093
  msgid "Value"
1094
  msgstr ""
1095
 
1096
- #: tmp/widgets/contact/contact.php:417
1097
  msgid "Spam Protection"
1098
  msgstr ""
1099
 
1100
- #: tmp/widgets/contact/contact.php:429
1101
  msgid "reCAPTCHA"
1102
  msgstr ""
1103
 
1104
- #: tmp/widgets/contact/contact.php:437
1105
  msgid "Use reCAPTCHA"
1106
  msgstr ""
1107
 
1108
- #: tmp/widgets/contact/contact.php:447
1109
  msgid "reCAPTCHA Site Key"
1110
  msgstr ""
1111
 
1112
- #: tmp/widgets/contact/contact.php:455
1113
  msgid "reCAPTCHA Secret Key"
1114
  msgstr ""
1115
 
1116
- #: tmp/widgets/contact/contact.php:463
1117
  msgid "Theme"
1118
  msgstr ""
1119
 
1120
- #: tmp/widgets/contact/contact.php:469
1121
  msgid "Light"
1122
  msgstr ""
1123
 
1124
- #: tmp/widgets/contact/contact.php:471
1125
  msgid "Dark"
1126
  msgstr ""
1127
 
1128
- #: tmp/widgets/contact/contact.php:481
1129
  msgid "Challenge type"
1130
  msgstr ""
1131
 
1132
- #: tmp/widgets/contact/contact.php:487, tmp/widgets/image-grid/image-grid.php:54, tmp/widgets/image-grid/image-grid.php:63, tmp/widgets/price-table/price-table.php:69, tmp/widgets/simple-masonry/simple-masonry.php:54, tmp/widgets/testimonial/testimonial.php:141, tmp/widgets/testimonial/testimonial.php:373
1133
  msgid "Image"
1134
  msgstr ""
1135
 
1136
- #: tmp/widgets/contact/contact.php:489
1137
  msgid "Audio"
1138
  msgstr ""
1139
 
1140
- #: tmp/widgets/contact/contact.php:499, tmp/widgets/contact/contact.php:919, tmp/widgets/features/features.php:283, tmp/widgets/features/features.php:325, tmp/widgets/features/features.php:367, tmp/widgets/icon/icon.php:40
1141
  msgid "Size"
1142
  msgstr ""
1143
 
1144
- #: tmp/widgets/contact/contact.php:507
1145
  msgid "Compact"
1146
  msgstr ""
1147
 
1148
- #: tmp/widgets/contact/contact.php:523
1149
  msgid "Akismet"
1150
  msgstr ""
1151
 
1152
- #: tmp/widgets/contact/contact.php:531
1153
  msgid "Use Akismet filtering"
1154
  msgstr ""
1155
 
1156
- #: tmp/widgets/contact/contact.php:541
1157
  msgid "Spam action"
1158
  msgstr ""
1159
 
1160
- #: tmp/widgets/contact/contact.php:545
1161
  msgid "Show error message"
1162
  msgstr ""
1163
 
1164
- #: tmp/widgets/contact/contact.php:547
1165
  msgid "Tag as spam in subject"
1166
  msgstr ""
1167
 
1168
- #: tmp/widgets/contact/contact.php:551
1169
  msgid "How to handle submissions that are identified as spam."
1170
  msgstr ""
1171
 
1172
- #: tmp/widgets/contact/contact.php:583
1173
  msgid "Container"
1174
  msgstr ""
1175
 
1176
- #: tmp/widgets/contact/contact.php:631, tmp/widgets/contact/contact.php:1079
1177
  msgid "Border style"
1178
  msgstr ""
1179
 
1180
- #: tmp/widgets/contact/contact.php:639, tmp/widgets/contact/contact.php:865, tmp/widgets/contact/contact.php:1257, tmp/widgets/image/image.php:63
1181
  msgid "Hidden"
1182
  msgstr ""
1183
 
1184
- #: tmp/widgets/contact/contact.php:641, tmp/widgets/contact/contact.php:867, tmp/widgets/contact/contact.php:1089, tmp/widgets/contact/contact.php:1239, tmp/widgets/headline/headline.php:187
1185
  msgid "Dotted"
1186
  msgstr ""
1187
 
1188
- #: tmp/widgets/contact/contact.php:643, tmp/widgets/contact/contact.php:869, tmp/widgets/contact/contact.php:1091, tmp/widgets/contact/contact.php:1241, tmp/widgets/headline/headline.php:188
1189
  msgid "Dashed"
1190
  msgstr ""
1191
 
1192
- #: tmp/widgets/contact/contact.php:645, tmp/widgets/contact/contact.php:871, tmp/widgets/contact/contact.php:1087, tmp/widgets/contact/contact.php:1243, tmp/widgets/headline/headline.php:186
1193
  msgid "Solid"
1194
  msgstr ""
1195
 
1196
- #: tmp/widgets/contact/contact.php:647, tmp/widgets/contact/contact.php:873, tmp/widgets/contact/contact.php:1245, tmp/widgets/headline/headline.php:189
1197
  msgid "Double"
1198
  msgstr ""
1199
 
1200
- #: tmp/widgets/contact/contact.php:649, tmp/widgets/contact/contact.php:875, tmp/widgets/contact/contact.php:1247, tmp/widgets/headline/headline.php:190
1201
  msgid "Groove"
1202
  msgstr ""
1203
 
1204
- #: tmp/widgets/contact/contact.php:651, tmp/widgets/contact/contact.php:877, tmp/widgets/contact/contact.php:1249, tmp/widgets/headline/headline.php:191
1205
  msgid "Ridge"
1206
  msgstr ""
1207
 
1208
- #: tmp/widgets/contact/contact.php:653, tmp/widgets/contact/contact.php:879, tmp/widgets/contact/contact.php:1251, tmp/widgets/headline/headline.php:192
1209
  msgid "Inset"
1210
  msgstr ""
1211
 
1212
- #: tmp/widgets/contact/contact.php:655, tmp/widgets/contact/contact.php:881, tmp/widgets/contact/contact.php:1253, tmp/widgets/headline/headline.php:193
1213
  msgid "Outset"
1214
  msgstr ""
1215
 
1216
- #: tmp/widgets/contact/contact.php:671
1217
  msgid "Field labels"
1218
  msgstr ""
1219
 
1220
- #: tmp/widgets/contact/contact.php:699, tmp/widgets/contact/contact.php:929, tmp/widgets/contact/contact.php:1267, tmp/widgets/features/features.php:291, tmp/widgets/features/features.php:333, tmp/widgets/features/features.php:375, tmp/widgets/google-map/google-map.php:693, tmp/widgets/headline/headline.php:67, tmp/widgets/headline/headline.php:138, tmp/widgets/headline/headline.php:198, tmp/widgets/icon/icon.php:35, tmp/widgets/taxonomy/taxonomy.php:55
1221
  msgid "Color"
1222
  msgstr ""
1223
 
1224
- #: tmp/widgets/contact/contact.php:709
1225
  msgid "Position"
1226
  msgstr ""
1227
 
1228
- #: tmp/widgets/contact/contact.php:715, tmp/widgets/image/image.php:64
1229
  msgid "Above"
1230
  msgstr ""
1231
 
1232
- #: tmp/widgets/contact/contact.php:717, tmp/widgets/image/image.php:65
1233
  msgid "Below"
1234
  msgstr ""
1235
 
1236
- #: tmp/widgets/contact/contact.php:723
1237
  msgid "Inside"
1238
  msgstr ""
1239
 
1240
- #: tmp/widgets/contact/contact.php:789, tmp/widgets/headline/headline.php:80, tmp/widgets/headline/headline.php:151
1241
  msgid "Font Size"
1242
  msgstr ""
1243
 
1244
- #: tmp/widgets/contact/contact.php:797, tmp/widgets/testimonial/testimonial.php:449
1245
  msgid "Text Color"
1246
  msgstr ""
1247
 
1248
- #: tmp/widgets/contact/contact.php:805, tmp/widgets/social-media-buttons/social-media-buttons.php:339
1249
  msgid "Margin"
1250
  msgstr ""
1251
 
1252
- #: tmp/widgets/contact/contact.php:821, tmp/widgets/google-map/google-map.php:185, tmp/widgets/hero/hero.php:321, tmp/widgets/layout-slider/layout-slider.php:124
1253
  msgid "Height"
1254
  msgstr ""
1255
 
1256
- #: tmp/widgets/contact/contact.php:829, tmp/widgets/hero/hero.php:169, tmp/widgets/layout-slider/layout-slider.php:52
1257
  msgid "Background"
1258
  msgstr ""
1259
 
1260
- #: tmp/widgets/contact/contact.php:857
1261
  msgid " Border style"
1262
  msgstr ""
1263
 
1264
- #: tmp/widgets/contact/contact.php:891, tmp/widgets/contact/contact.php:1111
1265
  msgid "Border rounding"
1266
  msgstr ""
1267
 
1268
- #: tmp/widgets/contact/contact.php:911
1269
  msgid "Field descriptions"
1270
  msgstr ""
1271
 
1272
- #: tmp/widgets/contact/contact.php:939, tmp/widgets/contact/contact.php:1233, tmp/widgets/google-map/google-map.php:599, tmp/widgets/headline/headline.php:182
1273
  msgid "Style"
1274
  msgstr ""
1275
 
1276
- #: tmp/widgets/contact/contact.php:945
1277
  msgid "Italic"
1278
  msgstr ""
1279
 
1280
- #: tmp/widgets/contact/contact.php:963
1281
  msgid "Error messages"
1282
  msgstr ""
1283
 
1284
- #: tmp/widgets/contact/contact.php:971
1285
  msgid "Error background color"
1286
  msgstr ""
1287
 
1288
- #: tmp/widgets/contact/contact.php:981
1289
  msgid "Error border color"
1290
  msgstr ""
1291
 
1292
- #: tmp/widgets/contact/contact.php:991
1293
  msgid "Error text color"
1294
  msgstr ""
1295
 
1296
- #: tmp/widgets/contact/contact.php:1001
1297
  msgid "Error padding"
1298
  msgstr ""
1299
 
1300
- #: tmp/widgets/contact/contact.php:1011
1301
  msgid "Error margin"
1302
  msgstr ""
1303
 
1304
- #: tmp/widgets/contact/contact.php:1027
1305
  msgid "Submit button"
1306
  msgstr ""
1307
 
1308
- #: tmp/widgets/contact/contact.php:1035
1309
  msgid "Style submit button"
1310
  msgstr ""
1311
 
1312
- #: tmp/widgets/contact/contact.php:1037
1313
  msgid "Style the button or leave it with default theme styling."
1314
  msgstr ""
1315
 
1316
- #: tmp/widgets/contact/contact.php:1059
1317
  msgid "Gradient intensity"
1318
  msgstr ""
1319
 
1320
- #: tmp/widgets/contact/contact.php:1145
1321
  msgid "Font weight"
1322
  msgstr ""
1323
 
1324
- #: tmp/widgets/contact/contact.php:1153
1325
  msgid "Semi-bold"
1326
  msgstr ""
1327
 
1328
- #: tmp/widgets/contact/contact.php:1155
1329
  msgid "Bold"
1330
  msgstr ""
1331
 
1332
- #: tmp/widgets/contact/contact.php:1203
1333
  msgid "Inset highlight"
1334
  msgstr ""
1335
 
1336
- #: tmp/widgets/contact/contact.php:1205
1337
  msgid "The white highlight at the bottom of the button"
1338
  msgstr ""
1339
 
1340
- #: tmp/widgets/contact/contact.php:1225
1341
  msgid "Input focus"
1342
  msgstr ""
1343
 
1344
- #: tmp/widgets/contact/contact.php:1319
1345
  msgid "Get more form fields for the Contact Form Widget in %s"
1346
  msgstr ""
1347
 
1348
- #: tmp/widgets/contact/contact.php:1321
1349
  msgid "SiteOrigin Premium"
1350
  msgstr ""
1351
 
1352
- #: tmp/widgets/contact/contact.php:1373
1353
  msgid "Your Name"
1354
  msgstr ""
1355
 
1356
- #: tmp/widgets/contact/contact.php:1379
1357
  msgid "Please enter your name"
1358
  msgstr ""
1359
 
1360
- #: tmp/widgets/contact/contact.php:1389
1361
  msgid "Your Email"
1362
  msgstr ""
1363
 
1364
- #: tmp/widgets/contact/contact.php:1395
1365
  msgid "Please enter a valid email address"
1366
  msgstr ""
1367
 
1368
- #: tmp/widgets/contact/contact.php:1411
1369
  msgid "Please enter a subject"
1370
  msgstr ""
1371
 
1372
- #: tmp/widgets/contact/contact.php:1421
1373
  msgid "Message"
1374
  msgstr ""
1375
 
1376
- #: tmp/widgets/contact/contact.php:1427
1377
  msgid "Please write something"
1378
  msgstr ""
1379
 
1380
- #: tmp/widgets/contact/contact.php:2019
1381
  msgid "Invalid email address."
1382
  msgstr ""
1383
 
1384
- #: tmp/widgets/contact/contact.php:2167
1385
  msgid "Error sending email, please try again later."
1386
  msgstr ""
1387
 
1388
- #: tmp/widgets/contact/contact.php:2215
1389
  msgid "A valid email is required"
1390
  msgstr ""
1391
 
1392
- #: tmp/widgets/contact/contact.php:2219
1393
  msgid "The email address is invalid"
1394
  msgstr ""
1395
 
1396
- #: tmp/widgets/contact/contact.php:2227
1397
  msgid "Missing subject"
1398
  msgstr ""
1399
 
1400
- #: tmp/widgets/contact/contact.php:2295
1401
  msgid "Error validating your Captcha response."
1402
  msgstr ""
1403
 
1404
- #: tmp/widgets/contact/contact.php:2359
1405
  msgid "Unfortunately our system identified your message as spam."
1406
  msgstr ""
1407
 
 
 
 
 
 
1408
  #: tmp/widgets/cta/cta.php:29
1409
  msgid "SiteOrigin Call-to-action"
1410
  msgstr ""
@@ -1433,19 +1463,19 @@ msgstr ""
1433
  msgid "Get more font customization options with %sSiteOrigin Premium%s"
1434
  msgstr ""
1435
 
1436
- #: tmp/widgets/editor/editor.php:16
1437
  msgid "SiteOrigin Editor"
1438
  msgstr ""
1439
 
1440
- #: tmp/widgets/editor/editor.php:18
1441
  msgid "A rich-text, text editor."
1442
  msgstr ""
1443
 
1444
- #: tmp/widgets/editor/editor.php:41
1445
  msgid "Automatically add paragraphs"
1446
  msgstr ""
1447
 
1448
- #: tmp/widgets/editor/editor.php:51
1449
  msgid "Enable the \"Automatically add paragraphs\" setting by default."
1450
  msgstr ""
1451
 
@@ -1489,7 +1519,7 @@ msgstr ""
1489
  msgid "Icon image size"
1490
  msgstr ""
1491
 
1492
- #: tmp/widgets/features/features.php:209, tmp/widgets/image/image.php:55
1493
  msgid "Title text"
1494
  msgstr ""
1495
 
@@ -1545,11 +1575,11 @@ msgstr ""
1545
  msgid "Open more URL in a new window"
1546
  msgstr ""
1547
 
1548
- #: tmp/widgets/features/features.php:591
1549
  msgid "Responsive Breakpoint"
1550
  msgstr ""
1551
 
1552
- #: tmp/widgets/features/features.php:595
1553
  msgid "This setting controls when the features widget will collapse for mobile devices. The default value is 520px"
1554
  msgstr ""
1555
 
@@ -1937,103 +1967,103 @@ msgstr ""
1937
  msgid "Custom Map"
1938
  msgstr ""
1939
 
1940
- #: tmp/widgets/headline/headline.php:16
1941
  msgid "SiteOrigin Headline"
1942
  msgstr ""
1943
 
1944
- #: tmp/widgets/headline/headline.php:18
1945
  msgid "A headline widget."
1946
  msgstr ""
1947
 
1948
- #: tmp/widgets/headline/headline.php:35, tmp/widgets/headline/headline.php:235
1949
  msgid "Headline"
1950
  msgstr ""
1951
 
1952
- #: tmp/widgets/headline/headline.php:53, tmp/widgets/headline/headline.php:124
1953
  msgid "HTML Tag"
1954
  msgstr ""
1955
 
1956
- #: tmp/widgets/headline/headline.php:56, tmp/widgets/headline/headline.php:127
1957
  msgid "H1"
1958
  msgstr ""
1959
 
1960
- #: tmp/widgets/headline/headline.php:57, tmp/widgets/headline/headline.php:128
1961
  msgid "H2"
1962
  msgstr ""
1963
 
1964
- #: tmp/widgets/headline/headline.php:58, tmp/widgets/headline/headline.php:129
1965
  msgid "H3"
1966
  msgstr ""
1967
 
1968
- #: tmp/widgets/headline/headline.php:59, tmp/widgets/headline/headline.php:130
1969
  msgid "H4"
1970
  msgstr ""
1971
 
1972
- #: tmp/widgets/headline/headline.php:60, tmp/widgets/headline/headline.php:131
1973
  msgid "H5"
1974
  msgstr ""
1975
 
1976
- #: tmp/widgets/headline/headline.php:61, tmp/widgets/headline/headline.php:132
1977
  msgid "H6"
1978
  msgstr ""
1979
 
1980
- #: tmp/widgets/headline/headline.php:62, tmp/widgets/headline/headline.php:133
1981
  msgid "Paragraph"
1982
  msgstr ""
1983
 
1984
- #: tmp/widgets/headline/headline.php:71, tmp/widgets/headline/headline.php:142
1985
  msgid "Hover Color"
1986
  msgstr ""
1987
 
1988
- #: tmp/widgets/headline/headline.php:84, tmp/widgets/headline/headline.php:155, tmp/widgets/headline/headline.php:210, tmp/widgets/icon/icon.php:45
1989
  msgid "Alignment"
1990
  msgstr ""
1991
 
1992
- #: tmp/widgets/headline/headline.php:95, tmp/widgets/headline/headline.php:166
1993
  msgid "Line Height"
1994
  msgstr ""
1995
 
1996
- #: tmp/widgets/headline/headline.php:99, tmp/widgets/headline/headline.php:170, tmp/widgets/headline/headline.php:225
1997
  msgid "Top and Bottom Margin"
1998
  msgstr ""
1999
 
2000
- #: tmp/widgets/headline/headline.php:106
2001
  msgid "Sub headline"
2002
  msgstr ""
2003
 
2004
- #: tmp/widgets/headline/headline.php:177, tmp/widgets/headline/headline.php:236
2005
  msgid "Divider"
2006
  msgstr ""
2007
 
2008
- #: tmp/widgets/headline/headline.php:203
2009
  msgid "Thickness"
2010
  msgstr ""
2011
 
2012
- #: tmp/widgets/headline/headline.php:220
2013
  msgid "Divider Width"
2014
  msgstr ""
2015
 
2016
- #: tmp/widgets/headline/headline.php:233
2017
  msgid "Element Order"
2018
  msgstr ""
2019
 
2020
- #: tmp/widgets/headline/headline.php:237
2021
  msgid "Sub Headline"
2022
  msgstr ""
2023
 
2024
- #: tmp/widgets/headline/headline.php:244, tmp/widgets/hero/hero.php:419
2025
  msgid "Use FitText"
2026
  msgstr ""
2027
 
2028
- #: tmp/widgets/headline/headline.php:245, tmp/widgets/hero/hero.php:421
2029
  msgid "Dynamically adjust your heading font size based on screen size."
2030
  msgstr ""
2031
 
2032
- #: tmp/widgets/headline/headline.php:258, tmp/widgets/hero/hero.php:447
2033
  msgid "FitText Compressor Strength"
2034
  msgstr ""
2035
 
2036
- #: tmp/widgets/headline/headline.php:259, tmp/widgets/hero/hero.php:449
2037
  msgid "How aggressively FitText should resize your heading."
2038
  msgstr ""
2039
 
@@ -2065,7 +2095,7 @@ msgstr ""
2065
  msgid "Background image"
2066
  msgstr ""
2067
 
2068
- #: tmp/widgets/hero/hero.php:191, tmp/widgets/image-grid/image-grid.php:86, tmp/widgets/image/image.php:38, tmp/widgets/testimonial/testimonial.php:259, tmp/widgets/testimonial/testimonial.php:317, tmp/widgets/testimonial/testimonial.php:401
2069
  msgid "Image size"
2070
  msgstr ""
2071
 
@@ -2185,7 +2215,7 @@ msgstr ""
2185
  msgid "URL"
2186
  msgstr ""
2187
 
2188
- #: tmp/widgets/image-grid/image-grid.php:76, tmp/widgets/image/image.php:81, tmp/widgets/slider/slider.php:89
2189
  msgid "Open in new window"
2190
  msgstr ""
2191
 
@@ -2209,47 +2239,47 @@ msgstr ""
2209
  msgid "Amount of spacing between images."
2210
  msgstr ""
2211
 
2212
- #: tmp/widgets/image-grid/image-grid.php:152, tmp/widgets/image/image.php:188
2213
  msgid "Add a Lightbox to your images with %sSiteOrigin Premium%s"
2214
  msgstr ""
2215
 
2216
- #: tmp/widgets/image/image.php:13
2217
  msgid "SiteOrigin Image"
2218
  msgstr ""
2219
 
2220
- #: tmp/widgets/image/image.php:15
2221
  msgid "A simple image widget with massive power."
2222
  msgstr ""
2223
 
2224
- #: tmp/widgets/image/image.php:31
2225
  msgid "Image file"
2226
  msgstr ""
2227
 
2228
- #: tmp/widgets/image/image.php:43
2229
  msgid "Image alignment"
2230
  msgstr ""
2231
 
2232
- #: tmp/widgets/image/image.php:60
2233
  msgid "Title position"
2234
  msgstr ""
2235
 
2236
- #: tmp/widgets/image/image.php:71
2237
  msgid "Alt text"
2238
  msgstr ""
2239
 
2240
- #: tmp/widgets/image/image.php:87
2241
  msgid "Bound"
2242
  msgstr ""
2243
 
2244
- #: tmp/widgets/image/image.php:88
2245
  msgid "Make sure the image doesn't extend beyond its container."
2246
  msgstr ""
2247
 
2248
- #: tmp/widgets/image/image.php:93
2249
  msgid "Full Width"
2250
  msgstr ""
2251
 
2252
- #: tmp/widgets/image/image.php:94
2253
  msgid "Resize image to fit its container."
2254
  msgstr ""
2255
 
17
  "X-Poedit-SearchPathExcluded-0: *.js\n"
18
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
 
20
+ #: tmp/admin/tpl/admin.php:17, tmp/so-widgets-bundle.php:399
21
  msgid "SiteOrigin Widgets Bundle"
22
  msgstr ""
23
 
69
  msgid "Save"
70
  msgstr ""
71
 
72
+ #: tmp/base/inc/actions.php:19, tmp/base/inc/actions.php:145, tmp/base/inc/actions.php:233, tmp/base/inc/actions.php:305, tmp/base/inc/actions.php:331, tmp/base/inc/actions.php:339, tmp/base/inc/actions.php:521, tmp/base/inc/actions.php:527, tmp/so-widgets-bundle.php:739, tmp/so-widgets-bundle.php:787, tmp/so-widgets-bundle.php:813, tmp/so-widgets-bundle.php:873, tmp/so-widgets-bundle.php:895, tmp/so-widgets-bundle.php:1027, tmp/so-widgets-bundle.php:1049
73
  msgid "Invalid request."
74
  msgstr ""
75
 
76
+ #: tmp/base/inc/actions.php:23, tmp/base/inc/actions.php:39, tmp/so-widgets-bundle.php:753, tmp/so-widgets-bundle.php:1039
77
  msgid "Invalid post."
78
  msgstr ""
79
 
80
+ #: tmp/base/inc/actions.php:95, tmp/base/siteorigin-widget.class.php:1273
81
  msgid "Widget Preview"
82
  msgstr ""
83
 
84
+ #: tmp/base/inc/actions.php:417
85
  msgid "Nonce error"
86
  msgstr ""
87
 
88
+ #: tmp/base/inc/actions.php:437
89
  msgid "Signature error"
90
  msgstr ""
91
 
92
+ #: tmp/base/inc/actions.php:489
93
  msgid "Attachment error"
94
  msgstr ""
95
 
117
  msgid "SiteOrigin Page Builder"
118
  msgstr ""
119
 
120
+ #: tmp/base/inc/fields/date-range.class.php:61
121
+ msgctxt "From this date"
122
  msgid "From"
123
  msgstr ""
124
 
125
+ #: tmp/base/inc/fields/date-range.class.php:67, tmp/base/inc/fields/date-range.class.php:95
126
  msgid "to"
127
  msgstr ""
128
 
129
+ #: tmp/base/inc/fields/date-range.class.php:89
130
+ msgid "From"
131
+ msgstr ""
132
+
133
+ #: tmp/base/inc/fields/date-range.class.php:127
134
  msgid "ago"
135
  msgstr ""
136
 
137
+ #: tmp/base/inc/fields/date-range.class.php:137
138
  msgid "days"
139
  msgstr ""
140
 
141
+ #: tmp/base/inc/fields/date-range.class.php:139
142
  msgid "weeks"
143
  msgstr ""
144
 
145
+ #: tmp/base/inc/fields/date-range.class.php:141
146
  msgid "months"
147
  msgstr ""
148
 
149
+ #: tmp/base/inc/fields/date-range.class.php:143
150
  msgid "years"
151
  msgstr ""
152
 
302
  msgid "Author"
303
  msgstr ""
304
 
305
+ #: tmp/base/inc/fields/posts.class.php:82, tmp/widgets/accordion/accordion.php:46, tmp/widgets/accordion/accordion.php:59, tmp/widgets/contact/contact.php:93, tmp/widgets/cta/cta.php:125, tmp/widgets/editor/editor.php:63, tmp/widgets/features/features.php:263, tmp/widgets/post-carousel/post-carousel.php:97, tmp/widgets/price-table/price-table.php:41, tmp/widgets/price-table/price-table.php:60, tmp/widgets/simple-masonry/simple-masonry.php:43, tmp/widgets/simple-masonry/simple-masonry.php:74, tmp/widgets/social-media-buttons/social-media-buttons.php:105, tmp/widgets/tabs/tabs.php:46, tmp/widgets/tabs/tabs.php:59, tmp/widgets/taxonomy/taxonomy.php:33, tmp/widgets/testimonial/testimonial.php:79, tmp/widgets/video/video.php:32
306
  msgid "Title"
307
  msgstr ""
308
 
362
  msgid "Sticky posts"
363
  msgstr ""
364
 
365
+ #: tmp/base/inc/fields/posts.class.php:115, tmp/compat/beaver-builder/beaver-builder.php:129, tmp/widgets/google-map/google-map.php:537, tmp/widgets/image/image.php:91
366
  msgid "Default"
367
  msgstr ""
368
 
506
  msgid "Maximum height"
507
  msgstr ""
508
 
509
+ #: tmp/base/inc/widgets/base-slider.class.php:349
510
+ msgid "display slide %s"
511
+ msgstr ""
512
+
513
+ #: tmp/base/inc/widgets/base-slider.class.php:359
514
+ msgid "next slide"
515
+ msgstr ""
516
+
517
+ #: tmp/base/inc/widgets/base-slider.class.php:371
518
+ msgid "previous slide"
519
+ msgstr ""
520
+
521
+ #: tmp/base/siteorigin-widget.class.php:961
522
  msgid "Preview"
523
  msgstr ""
524
 
525
+ #: tmp/base/siteorigin-widget.class.php:971
526
  msgid "Help"
527
  msgstr ""
528
 
529
+ #: tmp/base/siteorigin-widget.class.php:1103
530
  msgid "This widget has scripts and styles that need to be loaded before you can use it. Please save and reload your current page."
531
  msgstr ""
532
 
533
+ #: tmp/base/siteorigin-widget.class.php:1105
534
  msgid "You will only need to do this once."
535
  msgstr ""
536
 
537
+ #: tmp/base/siteorigin-widget.class.php:1159
538
  msgid "Are you sure?"
539
  msgstr ""
540
 
541
+ #: tmp/base/siteorigin-widget.class.php:1163
542
  msgid "There is a newer version of this widget's content available."
543
  msgstr ""
544
 
545
+ #: tmp/base/siteorigin-widget.class.php:1165, tmp/base/siteorigin-widget.class.php:1173
546
  msgid "Restore"
547
  msgstr ""
548
 
549
+ #: tmp/base/siteorigin-widget.class.php:1167
550
  msgid "Dismiss"
551
  msgstr ""
552
 
553
+ #: tmp/base/siteorigin-widget.class.php:1171
554
  msgid "Clicking %s will replace the current widget contents. You can revert by refreshing the page before updating."
555
  msgstr ""
556
 
582
  msgid "SiteOrigin Widget"
583
  msgstr ""
584
 
585
+ #: tmp/compat/visual-composer/visual-composer.php:40, tmp/so-widgets-bundle.php:927, tmp/so-widgets-bundle.php:929
586
  msgid "SiteOrigin Widgets"
587
  msgstr ""
588
 
618
  msgid "Ionicons"
619
  msgstr ""
620
 
621
+ #: tmp/so-widgets-bundle.php:431
622
  msgid "A new widget!"
623
  msgstr ""
624
 
625
+ #: tmp/so-widgets-bundle.php:747, tmp/so-widgets-bundle.php:793, tmp/so-widgets-bundle.php:879
626
  msgid "Insufficient permissions."
627
  msgstr ""
628
 
629
+ #: tmp/so-widgets-bundle.php:979
630
  msgid "%s was %s"
631
  msgstr ""
632
 
633
+ #: tmp/so-widgets-bundle.php:983
634
  msgid "Activated"
635
  msgstr ""
636
 
637
+ #: tmp/so-widgets-bundle.php:983
638
  msgid "Deactivated"
639
  msgstr ""
640
 
641
+ #: tmp/so-widgets-bundle.php:1491
642
  msgid "Manage Widgets"
643
  msgstr ""
644
 
645
+ #: tmp/so-widgets-bundle.php:1493
646
  msgid "Support"
647
  msgstr ""
648
 
678
  msgid "Closed"
679
  msgstr ""
680
 
681
+ #: tmp/widgets/accordion/accordion.php:79, tmp/widgets/contact/contact.php:583, tmp/widgets/cta/cta.php:145, tmp/widgets/tabs/tabs.php:75, tmp/widgets/testimonial/testimonial.php:363
682
  msgid "Design"
683
  msgstr ""
684
 
686
  msgid "Headings"
687
  msgstr ""
688
 
689
+ #: tmp/widgets/accordion/accordion.php:89, tmp/widgets/accordion/accordion.php:127, tmp/widgets/contact/contact.php:603, tmp/widgets/contact/contact.php:1061, tmp/widgets/cta/cta.php:153, tmp/widgets/hero/hero.php:235, tmp/widgets/layout-slider/layout-slider.php:81, tmp/widgets/social-media-buttons/social-media-buttons.php:169, tmp/widgets/tabs/tabs.php:85, tmp/widgets/tabs/tabs.php:105, tmp/widgets/tabs/tabs.php:149
690
  msgid "Background color"
691
  msgstr ""
692
 
702
  msgid "Title hover color"
703
  msgstr ""
704
 
705
+ #: tmp/widgets/accordion/accordion.php:108, tmp/widgets/accordion/accordion.php:136, tmp/widgets/contact/contact.php:623, tmp/widgets/contact/contact.php:849, tmp/widgets/contact/contact.php:1081, tmp/widgets/cta/cta.php:161, tmp/widgets/tabs/tabs.php:90, tmp/widgets/tabs/tabs.php:124, tmp/widgets/tabs/tabs.php:158
706
  msgid "Border color"
707
  msgstr ""
708
 
710
  msgid "Border hover color"
711
  msgstr ""
712
 
713
+ #: tmp/widgets/accordion/accordion.php:116, tmp/widgets/accordion/accordion.php:140, tmp/widgets/contact/contact.php:633, tmp/widgets/contact/contact.php:859, tmp/widgets/contact/contact.php:1113, tmp/widgets/tabs/tabs.php:94, tmp/widgets/tabs/tabs.php:134, tmp/widgets/tabs/tabs.php:162
714
  msgid "Border width"
715
  msgstr ""
716
 
738
  msgid "Button text"
739
  msgstr ""
740
 
741
+ #: tmp/widgets/button/button.php:99, tmp/widgets/google-map/google-map.php:193, tmp/widgets/headline/headline.php:87, tmp/widgets/headline/headline.php:229, tmp/widgets/hero/hero.php:247, tmp/widgets/icon/icon.php:56, tmp/widgets/image/image.php:151, tmp/widgets/layout-slider/layout-slider.php:87, tmp/widgets/simple-masonry/simple-masonry.php:78, tmp/widgets/slider/slider.php:84
742
  msgid "Destination URL"
743
  msgstr ""
744
 
745
+ #: tmp/widgets/button/button.php:111, tmp/widgets/google-map/google-map.php:215, tmp/widgets/headline/headline.php:97, tmp/widgets/headline/headline.php:239, tmp/widgets/icon/icon.php:62, tmp/widgets/simple-masonry/simple-masonry.php:83, tmp/widgets/social-media-buttons/social-media-buttons.php:191, tmp/widgets/taxonomy/taxonomy.php:64
746
  msgid "Open in a new window"
747
  msgstr ""
748
 
770
  msgid "Top"
771
  msgstr ""
772
 
773
+ #: tmp/widgets/button/button.php:169, tmp/widgets/button/button.php:221, tmp/widgets/contact/contact.php:733, tmp/widgets/contact/contact.php:763, tmp/widgets/contact/contact.php:1203, tmp/widgets/cta/cta.php:193, tmp/widgets/features/features.php:127, tmp/widgets/headline/headline.php:177, tmp/widgets/headline/headline.php:319, tmp/widgets/headline/headline.php:429, tmp/widgets/icon/icon.php:49, tmp/widgets/image/image.php:95, tmp/widgets/social-media-buttons/social-media-buttons.php:303, tmp/widgets/social-media-buttons/social-media-buttons.php:325, tmp/widgets/testimonial/testimonial.php:507
774
  msgid "Right"
775
  msgstr ""
776
 
778
  msgid "Bottom"
779
  msgstr ""
780
 
781
+ #: tmp/widgets/button/button.php:173, tmp/widgets/button/button.php:219, tmp/widgets/contact/contact.php:731, tmp/widgets/contact/contact.php:761, tmp/widgets/contact/contact.php:1201, tmp/widgets/cta/cta.php:191, tmp/widgets/features/features.php:131, tmp/widgets/headline/headline.php:175, tmp/widgets/headline/headline.php:317, tmp/widgets/headline/headline.php:427, tmp/widgets/icon/icon.php:48, tmp/widgets/image/image.php:93, tmp/widgets/social-media-buttons/social-media-buttons.php:301, tmp/widgets/social-media-buttons/social-media-buttons.php:323, tmp/widgets/testimonial/testimonial.php:505
782
  msgid "Left"
783
  msgstr ""
784
 
786
  msgid "Design and layout"
787
  msgstr ""
788
 
789
+ #: tmp/widgets/button/button.php:201, tmp/widgets/contact/contact.php:745, tmp/widgets/contact/contact.php:1187, tmp/widgets/contact/contact.php:1289, tmp/widgets/google-map/google-map.php:175
790
  msgid "Width"
791
  msgstr ""
792
 
794
  msgid "Leave blank to let the button resize according to content."
795
  msgstr ""
796
 
797
+ #: tmp/widgets/button/button.php:213, tmp/widgets/contact/contact.php:755, tmp/widgets/contact/contact.php:1195, tmp/widgets/social-media-buttons/social-media-buttons.php:295
798
  msgid "Align"
799
  msgstr ""
800
 
801
+ #: tmp/widgets/button/button.php:223, tmp/widgets/contact/contact.php:765, tmp/widgets/contact/contact.php:1205, tmp/widgets/headline/headline.php:173, tmp/widgets/headline/headline.php:315, tmp/widgets/headline/headline.php:425, tmp/widgets/icon/icon.php:47, tmp/widgets/image/image.php:97, tmp/widgets/social-media-buttons/social-media-buttons.php:305, tmp/widgets/social-media-buttons/social-media-buttons.php:327
802
  msgid "Center"
803
  msgstr ""
804
 
805
+ #: tmp/widgets/button/button.php:225, tmp/widgets/contact/contact.php:767, tmp/widgets/headline/headline.php:179, tmp/widgets/headline/headline.php:321, tmp/widgets/social-media-buttons/social-media-buttons.php:307, tmp/widgets/social-media-buttons/social-media-buttons.php:329
806
  msgid "Justify"
807
  msgstr ""
808
 
826
  msgid "Button color"
827
  msgstr ""
828
 
829
+ #: tmp/widgets/button/button.php:271, tmp/widgets/contact/contact.php:1137, tmp/widgets/hero/hero.php:485, tmp/widgets/layout-slider/layout-slider.php:181
830
  msgid "Text color"
831
  msgstr ""
832
 
834
  msgid "Use hover effects"
835
  msgstr ""
836
 
837
+ #: tmp/widgets/button/button.php:293, tmp/widgets/contact/contact.php:691, tmp/widgets/contact/contact.php:791, tmp/widgets/features/features.php:273, tmp/widgets/features/features.php:315, tmp/widgets/features/features.php:357, tmp/widgets/headline/headline.php:149, tmp/widgets/headline/headline.php:291
838
  msgid "Font"
839
  msgstr ""
840
 
841
+ #: tmp/widgets/button/button.php:305, tmp/widgets/contact/contact.php:701, tmp/widgets/contact/contact.php:1147
842
  msgid "Font size"
843
  msgstr ""
844
 
845
+ #: tmp/widgets/button/button.php:309, tmp/widgets/contact/contact.php:517, tmp/widgets/contact/contact.php:959, tmp/widgets/contact/contact.php:1163, tmp/widgets/social-media-buttons/social-media-buttons.php:235
846
  msgid "Normal"
847
  msgstr ""
848
 
858
  msgid "Rounding"
859
  msgstr ""
860
 
861
+ #: tmp/widgets/button/button.php:333, tmp/widgets/contact/contact.php:649, tmp/widgets/contact/contact.php:875, tmp/widgets/contact/contact.php:1097, tmp/widgets/contact/contact.php:1267, tmp/widgets/headline/headline.php:369, tmp/widgets/social-media-buttons/social-media-buttons.php:257
862
  msgid "None"
863
  msgstr ""
864
 
874
  msgid "Completely rounded"
875
  msgstr ""
876
 
877
+ #: tmp/widgets/button/button.php:351, tmp/widgets/contact/contact.php:613, tmp/widgets/contact/contact.php:825, tmp/widgets/contact/contact.php:1177, tmp/widgets/social-media-buttons/social-media-buttons.php:273, tmp/widgets/testimonial/testimonial.php:465
878
  msgid "Padding"
879
  msgstr ""
880
 
1018
  msgid "Fields marked with * are required"
1019
  msgstr ""
1020
 
1021
+ #: tmp/widgets/contact/contact.php:251
1022
+ msgid "Log IP addresses."
1023
+ msgstr ""
1024
+
1025
+ #: tmp/widgets/contact/contact.php:269, tmp/widgets/contact/contact.php:783
1026
  msgid "Fields"
1027
  msgstr ""
1028
 
1029
+ #: tmp/widgets/contact/contact.php:271
1030
  msgid "Field"
1031
  msgstr ""
1032
 
1033
+ #: tmp/widgets/contact/contact.php:287
1034
  msgid "Field Type"
1035
  msgstr ""
1036
 
1037
+ #: tmp/widgets/contact/contact.php:289
1038
  msgid "Select Field Type"
1039
  msgstr ""
1040
 
1041
+ #: tmp/widgets/contact/contact.php:293, tmp/widgets/testimonial/testimonial.php:107
1042
  msgid "Name"
1043
  msgstr ""
1044
 
1045
+ #: tmp/widgets/contact/contact.php:295, tmp/widgets/social-media-buttons/data/networks.php:29
1046
  msgid "Email"
1047
  msgstr ""
1048
 
1049
+ #: tmp/widgets/contact/contact.php:297
1050
+ msgid "Phone Number"
1051
+ msgstr ""
1052
+
1053
+ #: tmp/widgets/contact/contact.php:299, tmp/widgets/contact/contact.php:1417
1054
  msgid "Subject"
1055
  msgstr ""
1056
 
1057
+ #: tmp/widgets/contact/contact.php:301, tmp/widgets/features/features.php:219, tmp/widgets/features/features.php:305, tmp/widgets/headline/headline.php:79, tmp/widgets/headline/headline.php:221, tmp/widgets/price-table/price-table.php:110, tmp/widgets/taxonomy/taxonomy.php:50, tmp/widgets/testimonial/testimonial.php:161
1058
  msgid "Text"
1059
  msgstr ""
1060
 
1061
+ #: tmp/widgets/contact/contact.php:303
1062
  msgid "Text Area"
1063
  msgstr ""
1064
 
1065
+ #: tmp/widgets/contact/contact.php:305
1066
  msgid "Dropdown Select"
1067
  msgstr ""
1068
 
1069
+ #: tmp/widgets/contact/contact.php:307
1070
  msgid "Checkboxes"
1071
  msgstr ""
1072
 
1073
+ #: tmp/widgets/contact/contact.php:309
1074
  msgid "Radio"
1075
  msgstr ""
1076
 
1077
+ #: tmp/widgets/contact/contact.php:329, tmp/widgets/taxonomy/taxonomy.php:42
1078
  msgid "Label"
1079
  msgstr ""
1080
 
1081
+ #: tmp/widgets/contact/contact.php:339
1082
  msgid "Description"
1083
  msgstr ""
1084
 
1085
+ #: tmp/widgets/contact/contact.php:341
1086
  msgid "This text will appear small beneath the input field."
1087
  msgstr ""
1088
 
1089
+ #: tmp/widgets/contact/contact.php:351
1090
  msgid "Required Field"
1091
  msgstr ""
1092
 
1093
+ #: tmp/widgets/contact/contact.php:359, tmp/widgets/contact/contact.php:2007
1094
  msgid "Required field"
1095
  msgstr ""
1096
 
1097
+ #: tmp/widgets/contact/contact.php:361
1098
  msgid "Is this field required?"
1099
  msgstr ""
1100
 
1101
+ #: tmp/widgets/contact/contact.php:369
1102
  msgid "Missing message"
1103
  msgstr ""
1104
 
1105
+ #: tmp/widgets/contact/contact.php:371
1106
  msgid "Error message to display if this field is missing."
1107
  msgstr ""
1108
 
1109
+ #: tmp/widgets/contact/contact.php:387
1110
  msgid "Options"
1111
  msgstr ""
1112
 
1113
+ #: tmp/widgets/contact/contact.php:389
1114
  msgid "Option"
1115
  msgstr ""
1116
 
1117
+ #: tmp/widgets/contact/contact.php:399
1118
  msgid "Value"
1119
  msgstr ""
1120
 
1121
+ #: tmp/widgets/contact/contact.php:429
1122
  msgid "Spam Protection"
1123
  msgstr ""
1124
 
1125
+ #: tmp/widgets/contact/contact.php:441
1126
  msgid "reCAPTCHA"
1127
  msgstr ""
1128
 
1129
+ #: tmp/widgets/contact/contact.php:449
1130
  msgid "Use reCAPTCHA"
1131
  msgstr ""
1132
 
1133
+ #: tmp/widgets/contact/contact.php:459
1134
  msgid "reCAPTCHA Site Key"
1135
  msgstr ""
1136
 
1137
+ #: tmp/widgets/contact/contact.php:467
1138
  msgid "reCAPTCHA Secret Key"
1139
  msgstr ""
1140
 
1141
+ #: tmp/widgets/contact/contact.php:475
1142
  msgid "Theme"
1143
  msgstr ""
1144
 
1145
+ #: tmp/widgets/contact/contact.php:481
1146
  msgid "Light"
1147
  msgstr ""
1148
 
1149
+ #: tmp/widgets/contact/contact.php:483
1150
  msgid "Dark"
1151
  msgstr ""
1152
 
1153
+ #: tmp/widgets/contact/contact.php:493
1154
  msgid "Challenge type"
1155
  msgstr ""
1156
 
1157
+ #: tmp/widgets/contact/contact.php:499, tmp/widgets/image-grid/image-grid.php:54, tmp/widgets/image-grid/image-grid.php:63, tmp/widgets/price-table/price-table.php:69, tmp/widgets/simple-masonry/simple-masonry.php:54, tmp/widgets/testimonial/testimonial.php:141, tmp/widgets/testimonial/testimonial.php:373
1158
  msgid "Image"
1159
  msgstr ""
1160
 
1161
+ #: tmp/widgets/contact/contact.php:501
1162
  msgid "Audio"
1163
  msgstr ""
1164
 
1165
+ #: tmp/widgets/contact/contact.php:511, tmp/widgets/contact/contact.php:931, tmp/widgets/features/features.php:283, tmp/widgets/features/features.php:325, tmp/widgets/features/features.php:367, tmp/widgets/icon/icon.php:40
1166
  msgid "Size"
1167
  msgstr ""
1168
 
1169
+ #: tmp/widgets/contact/contact.php:519
1170
  msgid "Compact"
1171
  msgstr ""
1172
 
1173
+ #: tmp/widgets/contact/contact.php:535
1174
  msgid "Akismet"
1175
  msgstr ""
1176
 
1177
+ #: tmp/widgets/contact/contact.php:543
1178
  msgid "Use Akismet filtering"
1179
  msgstr ""
1180
 
1181
+ #: tmp/widgets/contact/contact.php:553
1182
  msgid "Spam action"
1183
  msgstr ""
1184
 
1185
+ #: tmp/widgets/contact/contact.php:557
1186
  msgid "Show error message"
1187
  msgstr ""
1188
 
1189
+ #: tmp/widgets/contact/contact.php:559
1190
  msgid "Tag as spam in subject"
1191
  msgstr ""
1192
 
1193
+ #: tmp/widgets/contact/contact.php:563
1194
  msgid "How to handle submissions that are identified as spam."
1195
  msgstr ""
1196
 
1197
+ #: tmp/widgets/contact/contact.php:595
1198
  msgid "Container"
1199
  msgstr ""
1200
 
1201
+ #: tmp/widgets/contact/contact.php:643, tmp/widgets/contact/contact.php:1091
1202
  msgid "Border style"
1203
  msgstr ""
1204
 
1205
+ #: tmp/widgets/contact/contact.php:651, tmp/widgets/contact/contact.php:877, tmp/widgets/contact/contact.php:1269, tmp/widgets/image/image.php:125
1206
  msgid "Hidden"
1207
  msgstr ""
1208
 
1209
+ #: tmp/widgets/contact/contact.php:653, tmp/widgets/contact/contact.php:879, tmp/widgets/contact/contact.php:1101, tmp/widgets/contact/contact.php:1251, tmp/widgets/headline/headline.php:373
1210
  msgid "Dotted"
1211
  msgstr ""
1212
 
1213
+ #: tmp/widgets/contact/contact.php:655, tmp/widgets/contact/contact.php:881, tmp/widgets/contact/contact.php:1103, tmp/widgets/contact/contact.php:1253, tmp/widgets/headline/headline.php:375
1214
  msgid "Dashed"
1215
  msgstr ""
1216
 
1217
+ #: tmp/widgets/contact/contact.php:657, tmp/widgets/contact/contact.php:883, tmp/widgets/contact/contact.php:1099, tmp/widgets/contact/contact.php:1255, tmp/widgets/headline/headline.php:371
1218
  msgid "Solid"
1219
  msgstr ""
1220
 
1221
+ #: tmp/widgets/contact/contact.php:659, tmp/widgets/contact/contact.php:885, tmp/widgets/contact/contact.php:1257, tmp/widgets/headline/headline.php:377
1222
  msgid "Double"
1223
  msgstr ""
1224
 
1225
+ #: tmp/widgets/contact/contact.php:661, tmp/widgets/contact/contact.php:887, tmp/widgets/contact/contact.php:1259, tmp/widgets/headline/headline.php:379
1226
  msgid "Groove"
1227
  msgstr ""
1228
 
1229
+ #: tmp/widgets/contact/contact.php:663, tmp/widgets/contact/contact.php:889, tmp/widgets/contact/contact.php:1261, tmp/widgets/headline/headline.php:381
1230
  msgid "Ridge"
1231
  msgstr ""
1232
 
1233
+ #: tmp/widgets/contact/contact.php:665, tmp/widgets/contact/contact.php:891, tmp/widgets/contact/contact.php:1263, tmp/widgets/headline/headline.php:383
1234
  msgid "Inset"
1235
  msgstr ""
1236
 
1237
+ #: tmp/widgets/contact/contact.php:667, tmp/widgets/contact/contact.php:893, tmp/widgets/contact/contact.php:1265, tmp/widgets/headline/headline.php:385
1238
  msgid "Outset"
1239
  msgstr ""
1240
 
1241
+ #: tmp/widgets/contact/contact.php:683
1242
  msgid "Field labels"
1243
  msgstr ""
1244
 
1245
+ #: tmp/widgets/contact/contact.php:711, tmp/widgets/contact/contact.php:941, tmp/widgets/contact/contact.php:1279, tmp/widgets/features/features.php:291, tmp/widgets/features/features.php:333, tmp/widgets/features/features.php:375, tmp/widgets/google-map/google-map.php:693, tmp/widgets/headline/headline.php:133, tmp/widgets/headline/headline.php:275, tmp/widgets/headline/headline.php:395, tmp/widgets/icon/icon.php:35, tmp/widgets/taxonomy/taxonomy.php:55
1246
  msgid "Color"
1247
  msgstr ""
1248
 
1249
+ #: tmp/widgets/contact/contact.php:721
1250
  msgid "Position"
1251
  msgstr ""
1252
 
1253
+ #: tmp/widgets/contact/contact.php:727, tmp/widgets/image/image.php:127
1254
  msgid "Above"
1255
  msgstr ""
1256
 
1257
+ #: tmp/widgets/contact/contact.php:729, tmp/widgets/image/image.php:129
1258
  msgid "Below"
1259
  msgstr ""
1260
 
1261
+ #: tmp/widgets/contact/contact.php:735
1262
  msgid "Inside"
1263
  msgstr ""
1264
 
1265
+ #: tmp/widgets/contact/contact.php:801, tmp/widgets/headline/headline.php:159, tmp/widgets/headline/headline.php:301
1266
  msgid "Font Size"
1267
  msgstr ""
1268
 
1269
+ #: tmp/widgets/contact/contact.php:809, tmp/widgets/testimonial/testimonial.php:449
1270
  msgid "Text Color"
1271
  msgstr ""
1272
 
1273
+ #: tmp/widgets/contact/contact.php:817, tmp/widgets/social-media-buttons/social-media-buttons.php:339
1274
  msgid "Margin"
1275
  msgstr ""
1276
 
1277
+ #: tmp/widgets/contact/contact.php:833, tmp/widgets/google-map/google-map.php:185, tmp/widgets/hero/hero.php:321, tmp/widgets/layout-slider/layout-slider.php:124
1278
  msgid "Height"
1279
  msgstr ""
1280
 
1281
+ #: tmp/widgets/contact/contact.php:841, tmp/widgets/hero/hero.php:169, tmp/widgets/layout-slider/layout-slider.php:52
1282
  msgid "Background"
1283
  msgstr ""
1284
 
1285
+ #: tmp/widgets/contact/contact.php:869
1286
  msgid " Border style"
1287
  msgstr ""
1288
 
1289
+ #: tmp/widgets/contact/contact.php:903, tmp/widgets/contact/contact.php:1123
1290
  msgid "Border rounding"
1291
  msgstr ""
1292
 
1293
+ #: tmp/widgets/contact/contact.php:923
1294
  msgid "Field descriptions"
1295
  msgstr ""
1296
 
1297
+ #: tmp/widgets/contact/contact.php:951, tmp/widgets/contact/contact.php:1245, tmp/widgets/google-map/google-map.php:599, tmp/widgets/headline/headline.php:363
1298
  msgid "Style"
1299
  msgstr ""
1300
 
1301
+ #: tmp/widgets/contact/contact.php:957
1302
  msgid "Italic"
1303
  msgstr ""
1304
 
1305
+ #: tmp/widgets/contact/contact.php:975
1306
  msgid "Error messages"
1307
  msgstr ""
1308
 
1309
+ #: tmp/widgets/contact/contact.php:983
1310
  msgid "Error background color"
1311
  msgstr ""
1312
 
1313
+ #: tmp/widgets/contact/contact.php:993
1314
  msgid "Error border color"
1315
  msgstr ""
1316
 
1317
+ #: tmp/widgets/contact/contact.php:1003
1318
  msgid "Error text color"
1319
  msgstr ""
1320
 
1321
+ #: tmp/widgets/contact/contact.php:1013
1322
  msgid "Error padding"
1323
  msgstr ""
1324
 
1325
+ #: tmp/widgets/contact/contact.php:1023
1326
  msgid "Error margin"
1327
  msgstr ""
1328
 
1329
+ #: tmp/widgets/contact/contact.php:1039
1330
  msgid "Submit button"
1331
  msgstr ""
1332
 
1333
+ #: tmp/widgets/contact/contact.php:1047
1334
  msgid "Style submit button"
1335
  msgstr ""
1336
 
1337
+ #: tmp/widgets/contact/contact.php:1049
1338
  msgid "Style the button or leave it with default theme styling."
1339
  msgstr ""
1340
 
1341
+ #: tmp/widgets/contact/contact.php:1071
1342
  msgid "Gradient intensity"
1343
  msgstr ""
1344
 
1345
+ #: tmp/widgets/contact/contact.php:1157
1346
  msgid "Font weight"
1347
  msgstr ""
1348
 
1349
+ #: tmp/widgets/contact/contact.php:1165
1350
  msgid "Semi-bold"
1351
  msgstr ""
1352
 
1353
+ #: tmp/widgets/contact/contact.php:1167
1354
  msgid "Bold"
1355
  msgstr ""
1356
 
1357
+ #: tmp/widgets/contact/contact.php:1215
1358
  msgid "Inset highlight"
1359
  msgstr ""
1360
 
1361
+ #: tmp/widgets/contact/contact.php:1217
1362
  msgid "The white highlight at the bottom of the button"
1363
  msgstr ""
1364
 
1365
+ #: tmp/widgets/contact/contact.php:1237
1366
  msgid "Input focus"
1367
  msgstr ""
1368
 
1369
+ #: tmp/widgets/contact/contact.php:1331
1370
  msgid "Get more form fields for the Contact Form Widget in %s"
1371
  msgstr ""
1372
 
1373
+ #: tmp/widgets/contact/contact.php:1333
1374
  msgid "SiteOrigin Premium"
1375
  msgstr ""
1376
 
1377
+ #: tmp/widgets/contact/contact.php:1385
1378
  msgid "Your Name"
1379
  msgstr ""
1380
 
1381
+ #: tmp/widgets/contact/contact.php:1391
1382
  msgid "Please enter your name"
1383
  msgstr ""
1384
 
1385
+ #: tmp/widgets/contact/contact.php:1401
1386
  msgid "Your Email"
1387
  msgstr ""
1388
 
1389
+ #: tmp/widgets/contact/contact.php:1407
1390
  msgid "Please enter a valid email address"
1391
  msgstr ""
1392
 
1393
+ #: tmp/widgets/contact/contact.php:1423
1394
  msgid "Please enter a subject"
1395
  msgstr ""
1396
 
1397
+ #: tmp/widgets/contact/contact.php:1433
1398
  msgid "Message"
1399
  msgstr ""
1400
 
1401
+ #: tmp/widgets/contact/contact.php:1439
1402
  msgid "Please write something"
1403
  msgstr ""
1404
 
1405
+ #: tmp/widgets/contact/contact.php:2031
1406
  msgid "Invalid email address."
1407
  msgstr ""
1408
 
1409
+ #: tmp/widgets/contact/contact.php:2179
1410
  msgid "Error sending email, please try again later."
1411
  msgstr ""
1412
 
1413
+ #: tmp/widgets/contact/contact.php:2227
1414
  msgid "A valid email is required"
1415
  msgstr ""
1416
 
1417
+ #: tmp/widgets/contact/contact.php:2231
1418
  msgid "The email address is invalid"
1419
  msgstr ""
1420
 
1421
+ #: tmp/widgets/contact/contact.php:2239
1422
  msgid "Missing subject"
1423
  msgstr ""
1424
 
1425
+ #: tmp/widgets/contact/contact.php:2307
1426
  msgid "Error validating your Captcha response."
1427
  msgstr ""
1428
 
1429
+ #: tmp/widgets/contact/contact.php:2371
1430
  msgid "Unfortunately our system identified your message as spam."
1431
  msgstr ""
1432
 
1433
+ #: tmp/widgets/contact/contact.php:2387
1434
+ msgctxt "The name of who sent this email"
1435
+ msgid "From"
1436
+ msgstr ""
1437
+
1438
  #: tmp/widgets/cta/cta.php:29
1439
  msgid "SiteOrigin Call-to-action"
1440
  msgstr ""
1463
  msgid "Get more font customization options with %sSiteOrigin Premium%s"
1464
  msgstr ""
1465
 
1466
+ #: tmp/widgets/editor/editor.php:31
1467
  msgid "SiteOrigin Editor"
1468
  msgstr ""
1469
 
1470
+ #: tmp/widgets/editor/editor.php:35
1471
  msgid "A rich-text, text editor."
1472
  msgstr ""
1473
 
1474
+ #: tmp/widgets/editor/editor.php:83
1475
  msgid "Automatically add paragraphs"
1476
  msgstr ""
1477
 
1478
+ #: tmp/widgets/editor/editor.php:103
1479
  msgid "Enable the \"Automatically add paragraphs\" setting by default."
1480
  msgstr ""
1481
 
1519
  msgid "Icon image size"
1520
  msgstr ""
1521
 
1522
+ #: tmp/widgets/features/features.php:209, tmp/widgets/image/image.php:109
1523
  msgid "Title text"
1524
  msgstr ""
1525
 
1575
  msgid "Open more URL in a new window"
1576
  msgstr ""
1577
 
1578
+ #: tmp/widgets/features/features.php:593
1579
  msgid "Responsive Breakpoint"
1580
  msgstr ""
1581
 
1582
+ #: tmp/widgets/features/features.php:597
1583
  msgid "This setting controls when the features widget will collapse for mobile devices. The default value is 520px"
1584
  msgstr ""
1585
 
1967
  msgid "Custom Map"
1968
  msgstr ""
1969
 
1970
+ #: tmp/widgets/headline/headline.php:31
1971
  msgid "SiteOrigin Headline"
1972
  msgstr ""
1973
 
1974
+ #: tmp/widgets/headline/headline.php:35
1975
  msgid "A headline widget."
1976
  msgstr ""
1977
 
1978
+ #: tmp/widgets/headline/headline.php:69, tmp/widgets/headline/headline.php:469
1979
  msgid "Headline"
1980
  msgstr ""
1981
 
1982
+ #: tmp/widgets/headline/headline.php:105, tmp/widgets/headline/headline.php:247
1983
  msgid "HTML Tag"
1984
  msgstr ""
1985
 
1986
+ #: tmp/widgets/headline/headline.php:111, tmp/widgets/headline/headline.php:253
1987
  msgid "H1"
1988
  msgstr ""
1989
 
1990
+ #: tmp/widgets/headline/headline.php:113, tmp/widgets/headline/headline.php:255
1991
  msgid "H2"
1992
  msgstr ""
1993
 
1994
+ #: tmp/widgets/headline/headline.php:115, tmp/widgets/headline/headline.php:257
1995
  msgid "H3"
1996
  msgstr ""
1997
 
1998
+ #: tmp/widgets/headline/headline.php:117, tmp/widgets/headline/headline.php:259
1999
  msgid "H4"
2000
  msgstr ""
2001
 
2002
+ #: tmp/widgets/headline/headline.php:119, tmp/widgets/headline/headline.php:261
2003
  msgid "H5"
2004
  msgstr ""
2005
 
2006
+ #: tmp/widgets/headline/headline.php:121, tmp/widgets/headline/headline.php:263
2007
  msgid "H6"
2008
  msgstr ""
2009
 
2010
+ #: tmp/widgets/headline/headline.php:123, tmp/widgets/headline/headline.php:265
2011
  msgid "Paragraph"
2012
  msgstr ""
2013
 
2014
+ #: tmp/widgets/headline/headline.php:141, tmp/widgets/headline/headline.php:283
2015
  msgid "Hover Color"
2016
  msgstr ""
2017
 
2018
+ #: tmp/widgets/headline/headline.php:167, tmp/widgets/headline/headline.php:309, tmp/widgets/headline/headline.php:419, tmp/widgets/icon/icon.php:45
2019
  msgid "Alignment"
2020
  msgstr ""
2021
 
2022
+ #: tmp/widgets/headline/headline.php:189, tmp/widgets/headline/headline.php:331
2023
  msgid "Line Height"
2024
  msgstr ""
2025
 
2026
+ #: tmp/widgets/headline/headline.php:197, tmp/widgets/headline/headline.php:339, tmp/widgets/headline/headline.php:449
2027
  msgid "Top and Bottom Margin"
2028
  msgstr ""
2029
 
2030
+ #: tmp/widgets/headline/headline.php:211
2031
  msgid "Sub headline"
2032
  msgstr ""
2033
 
2034
+ #: tmp/widgets/headline/headline.php:353, tmp/widgets/headline/headline.php:471
2035
  msgid "Divider"
2036
  msgstr ""
2037
 
2038
+ #: tmp/widgets/headline/headline.php:405
2039
  msgid "Thickness"
2040
  msgstr ""
2041
 
2042
+ #: tmp/widgets/headline/headline.php:439
2043
  msgid "Divider Width"
2044
  msgstr ""
2045
 
2046
+ #: tmp/widgets/headline/headline.php:465
2047
  msgid "Element Order"
2048
  msgstr ""
2049
 
2050
+ #: tmp/widgets/headline/headline.php:473
2051
  msgid "Sub Headline"
2052
  msgstr ""
2053
 
2054
+ #: tmp/widgets/headline/headline.php:487, tmp/widgets/hero/hero.php:419
2055
  msgid "Use FitText"
2056
  msgstr ""
2057
 
2058
+ #: tmp/widgets/headline/headline.php:489, tmp/widgets/hero/hero.php:421
2059
  msgid "Dynamically adjust your heading font size based on screen size."
2060
  msgstr ""
2061
 
2062
+ #: tmp/widgets/headline/headline.php:515, tmp/widgets/hero/hero.php:447
2063
  msgid "FitText Compressor Strength"
2064
  msgstr ""
2065
 
2066
+ #: tmp/widgets/headline/headline.php:517, tmp/widgets/hero/hero.php:449
2067
  msgid "How aggressively FitText should resize your heading."
2068
  msgstr ""
2069
 
2095
  msgid "Background image"
2096
  msgstr ""
2097
 
2098
+ #: tmp/widgets/hero/hero.php:191, tmp/widgets/image-grid/image-grid.php:86, tmp/widgets/image/image.php:75, tmp/widgets/testimonial/testimonial.php:259, tmp/widgets/testimonial/testimonial.php:317, tmp/widgets/testimonial/testimonial.php:401
2099
  msgid "Image size"
2100
  msgstr ""
2101
 
2215
  msgid "URL"
2216
  msgstr ""
2217
 
2218
+ #: tmp/widgets/image-grid/image-grid.php:76, tmp/widgets/image/image.php:161, tmp/widgets/slider/slider.php:89
2219
  msgid "Open in new window"
2220
  msgstr ""
2221
 
2239
  msgid "Amount of spacing between images."
2240
  msgstr ""
2241
 
2242
+ #: tmp/widgets/image-grid/image-grid.php:152, tmp/widgets/image/image.php:375
2243
  msgid "Add a Lightbox to your images with %sSiteOrigin Premium%s"
2244
  msgstr ""
2245
 
2246
+ #: tmp/widgets/image/image.php:25
2247
  msgid "SiteOrigin Image"
2248
  msgstr ""
2249
 
2250
+ #: tmp/widgets/image/image.php:29
2251
  msgid "A simple image widget with massive power."
2252
  msgstr ""
2253
 
2254
+ #: tmp/widgets/image/image.php:61
2255
  msgid "Image file"
2256
  msgstr ""
2257
 
2258
+ #: tmp/widgets/image/image.php:85
2259
  msgid "Image alignment"
2260
  msgstr ""
2261
 
2262
+ #: tmp/widgets/image/image.php:119
2263
  msgid "Title position"
2264
  msgstr ""
2265
 
2266
+ #: tmp/widgets/image/image.php:141
2267
  msgid "Alt text"
2268
  msgstr ""
2269
 
2270
+ #: tmp/widgets/image/image.php:173
2271
  msgid "Bound"
2272
  msgstr ""
2273
 
2274
+ #: tmp/widgets/image/image.php:175
2275
  msgid "Make sure the image doesn't extend beyond its container."
2276
  msgstr ""
2277
 
2278
+ #: tmp/widgets/image/image.php:185
2279
  msgid "Full Width"
2280
  msgstr ""
2281
 
2282
+ #: tmp/widgets/image/image.php:187
2283
  msgid "Resize image to fit its container."
2284
  msgstr ""
2285
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Tags: bundle, widget, button, slider, image, carousel, price table, google maps, tinymce, social links
3
  Requires at least: 4.2
4
  Tested up to: 4.9.1
5
- Stable tag: 1.11.4
6
- Build time: 2018-02-07T08:38:59+02:00
7
  License: GPLv3 or later
8
  Contributors: gpriday, braam-genis
9
  Donate link: https://siteorigin.com/downloads/contribution/
@@ -65,6 +65,24 @@ The SiteOrigin Widgets Bundle is the perfect platform to build widgets for your
65
 
66
  == Changelog ==
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  = 1.11.4 - 7 February 2018 =
69
  * Slider: Add playsinline for Video backgrounds for iOS.
70
  * Repeater field: Trigger change events for repeater when adding, removing or duplicating items.
2
  Tags: bundle, widget, button, slider, image, carousel, price table, google maps, tinymce, social links
3
  Requires at least: 4.2
4
  Tested up to: 4.9.1
5
+ Stable tag: 1.11.5
6
+ Build time: 2018-03-13T10:14:26+02:00
7
  License: GPLv3 or later
8
  Contributors: gpriday, braam-genis
9
  Donate link: https://siteorigin.com/downloads/contribution/
65
 
66
  == Changelog ==
67
 
68
+ = 1.11.5 - 13 March 2018 =
69
+ * Features: Better feature padding removal on row ends.
70
+ * Sliders: WCAG 2.4.4 compliance.
71
+ * Tabs: Hide widget title when no title is set.
72
+ * TinyMCE field: Added setting for `wpautop` processing which is on by default.
73
+ * Contact: When Gradient disabled, set basic background.
74
+ * Beaver Builder compat: Only set SOWB widget form values when editing a SOWB widget.
75
+ * Contact: Option to log submitter's IP address.
76
+ * Add random number and set `more_entropy` to increase chance of unique form ids.
77
+ * Contact: Added 'tel' field type which should show numeric keyboard on mobile.
78
+ * Media field: Trigger change event when removing selected image.
79
+ * Renamed the PHP LESS parser to `SiteOrigin_LessC` to avoid conflicts.
80
+ * Date range field: Prevent initializing date range fields multiple times and ensure date format consistent.
81
+ * Register pikaday as common script and enqueue as needed in fields.
82
+ * Google Map: Show satellite map type.
83
+ * Translation: Add context to From strings.
84
+ * Add missing semicolons to Ionicons codes.
85
+
86
  = 1.11.4 - 7 February 2018 =
87
  * Slider: Add playsinline for Video backgrounds for iOS.
88
  * Repeater field: Trigger change events for repeater when adding, removing or duplicating items.
so-widgets-bundle.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: SiteOrigin Widgets Bundle
4
  Description: A collection of all widgets, neatly bundled into a single plugin. It's also a framework to code your own widgets on top of.
5
- Version: 1.11.4
6
  Text Domain: so-widgets-bundle
7
  Domain Path: /lang
8
  Author: SiteOrigin
@@ -12,7 +12,7 @@ License: GPL3
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.txt
13
  */
14
 
15
- define('SOW_BUNDLE_VERSION', '1.11.4');
16
  define('SOW_BUNDLE_BASE_FILE', __FILE__);
17
 
18
  // Allow JS suffix to be pre-set
@@ -48,6 +48,7 @@ class SiteOrigin_Widgets_Bundle {
48
  add_action('admin_init', array($this, 'admin_activate_widget') );
49
  add_action('admin_menu', array($this, 'admin_menu_init') );
50
  add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts') );
 
51
 
52
  // All the ajax actions
53
  add_action('wp_ajax_so_widgets_bundle_manage', array($this, 'admin_ajax_manage_handler') );
@@ -310,7 +311,7 @@ class SiteOrigin_Widgets_Bundle {
310
  'toggleUrl' => wp_nonce_url( admin_url('admin-ajax.php?action=so_widgets_bundle_manage'), 'manage_so_widget' )
311
  ) );
312
  }
313
-
314
  /**
315
  * The fallback (from ajax) URL handler for activating or deactivating a widget
316
  */
@@ -342,7 +343,23 @@ class SiteOrigin_Widgets_Bundle {
342
 
343
  }
344
  }
345
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  /**
347
  * Handler for activating and deactivating widgets.
348
  *
@@ -732,7 +749,8 @@ class SiteOrigin_Widgets_Bundle {
732
  }
733
 
734
  function register_general_scripts() {
735
- wp_register_script( 'sow-fittext',
 
736
  plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'js/sow.jquery.fittext' . SOW_BUNDLE_JS_SUFFIX . '.js',
737
  array( 'jquery' ),
738
  '1.2',
2
  /*
3
  Plugin Name: SiteOrigin Widgets Bundle
4
  Description: A collection of all widgets, neatly bundled into a single plugin. It's also a framework to code your own widgets on top of.
5
+ Version: 1.11.5
6
  Text Domain: so-widgets-bundle
7
  Domain Path: /lang
8
  Author: SiteOrigin
12
  License URI: https://www.gnu.org/licenses/gpl-3.0.txt
13
  */
14
 
15
+ define('SOW_BUNDLE_VERSION', '1.11.5');
16
  define('SOW_BUNDLE_BASE_FILE', __FILE__);
17
 
18
  // Allow JS suffix to be pre-set
48
  add_action('admin_init', array($this, 'admin_activate_widget') );
49
  add_action('admin_menu', array($this, 'admin_menu_init') );
50
  add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts') );
51
+ add_action('admin_enqueue_scripts', array($this, 'admin_register_scripts') );
52
 
53
  // All the ajax actions
54
  add_action('wp_ajax_so_widgets_bundle_manage', array($this, 'admin_ajax_manage_handler') );
311
  'toggleUrl' => wp_nonce_url( admin_url('admin-ajax.php?action=so_widgets_bundle_manage'), 'manage_so_widget' )
312
  ) );
313
  }
314
+
315
  /**
316
  * The fallback (from ajax) URL handler for activating or deactivating a widget
317
  */
343
 
344
  }
345
  }
346
+
347
+ /**
348
+ * Register some common scripts used in forms.
349
+ */
350
+ function admin_register_scripts() {
351
+ wp_register_script(
352
+ 'sowb-pikaday',
353
+ plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'js/lib/pikaday' . SOW_BUNDLE_JS_SUFFIX . '.js',
354
+ array( ),
355
+ '1.5.1'
356
+ );
357
+ wp_register_style(
358
+ 'sowb-pikaday',
359
+ plugin_dir_url(__FILE__) . 'js/lib/pikaday.css'
360
+ );
361
+ }
362
+
363
  /**
364
  * Handler for activating and deactivating widgets.
365
  *
749
  }
750
 
751
  function register_general_scripts() {
752
+ wp_register_script(
753
+ 'sowb-fittext',
754
  plugin_dir_url( SOW_BUNDLE_BASE_FILE ) . 'js/sow.jquery.fittext' . SOW_BUNDLE_JS_SUFFIX . '.js',
755
  array( 'jquery' ),
756
  '1.2',
widgets/contact/contact.php CHANGED
@@ -121,6 +121,11 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
121
  'required_fields[hide]' => array( 'hide' ),
122
  )
123
  ),
 
 
 
 
 
124
  ),
125
  ),
126
 
@@ -141,6 +146,7 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
141
  'options' => array(
142
  'name' => __( 'Name', 'so-widgets-bundle' ),
143
  'email' => __( 'Email', 'so-widgets-bundle' ),
 
144
  'subject' => __( 'Subject', 'so-widgets-bundle' ),
145
  'text' => __( 'Text', 'so-widgets-bundle' ),
146
  'textarea' => __( 'Text Area', 'so-widgets-bundle' ),
@@ -1185,7 +1191,11 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
1185
  }
1186
 
1187
  function send_mail( $email_fields, $instance ) {
1188
- $body = '<strong>' . __( 'From', 'so-widgets-bundle' ) . ':</strong> <a href="mailto:' . sanitize_email( $email_fields['email'] ) . '">' . esc_html( $email_fields['name'] ) . '</a> &#60;' . sanitize_email( $email_fields['email'] ) . "&#62; \n\n";
 
 
 
 
1189
  foreach ( $email_fields['message'] as $m ) {
1190
  $body .= '<strong>' . $m['label'] . ':</strong>';
1191
  $body .= "\n";
@@ -1206,7 +1216,7 @@ class SiteOrigin_Widgets_ContactForm_Widget extends SiteOrigin_Widget {
1206
 
1207
  $headers = array(
1208
  'Content-Type: text/html; charset=UTF-8',
1209
- 'From: ' . $this->sanitize_header( $email_fields['name'] ) . ' <' . $instance['settings']['from'] . '>',
1210
  'Reply-To: ' . $this->sanitize_header( $email_fields['name'] ) . ' <' . sanitize_email( $email_fields['email'] ) . '>',
1211
  );
1212
 
121
  'required_fields[hide]' => array( 'hide' ),
122
  )
123
  ),
124
+ 'log_ip_address' => array(
125
+ 'type' => 'checkbox',
126
+ 'label' => __( 'Log IP addresses.', 'so-widgets-bundle' ),
127
+ 'default' => false,
128
+ ),
129
  ),
130
  ),
131
 
146
  'options' => array(
147
  'name' => __( 'Name', 'so-widgets-bundle' ),
148
  'email' => __( 'Email', 'so-widgets-bundle' ),
149
+ 'tel' => __( 'Phone Number', 'so-widgets-bundle' ),
150
  'subject' => __( 'Subject', 'so-widgets-bundle' ),
151
  'text' => __( 'Text', 'so-widgets-bundle' ),
152
  'textarea' => __( 'Text Area', 'so-widgets-bundle' ),
1191
  }
1192
 
1193
  function send_mail( $email_fields, $instance ) {
1194
+ $body = '<strong>' . _x( 'From', 'The name of who sent this email', 'so-widgets-bundle' ) . ':</strong> ' .
1195
+ '<a href="mailto:' . sanitize_email( $email_fields['email'] ) . '">' . esc_html( $email_fields['name'] ) . '</a> ' .
1196
+ '&#60;' . sanitize_email( $email_fields['email'] ) . '&#62; ' .
1197
+ ( ! empty( $instance['settings']['log_ip_address'] ) ? '( ' . $_SERVER['REMOTE_ADDR'] . ' )' : '' ) .
1198
+ "\n\n";
1199
  foreach ( $email_fields['message'] as $m ) {
1200
  $body .= '<strong>' . $m['label'] . ':</strong>';
1201
  $body .= "\n";
1216
 
1217
  $headers = array(
1218
  'Content-Type: text/html; charset=UTF-8',
1219
+ 'From: ' . $this->sanitize_header( $email_fields['name'] ) . ' <' . sanitize_email( $instance['settings']['from'] ) . '>',
1220
  'Reply-To: ' . $this->sanitize_header( $email_fields['name'] ) . ' <' . sanitize_email( $email_fields['email'] ) . '>',
1221
  );
1222
 
widgets/contact/fields/tel.class.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class SiteOrigin_Widget_ContactForm_Field_Tel extends SiteOrigin_Widget_ContactForm_Field_Text {
4
+ // This class just exists for autoloading purposes, but is the same as the text field.
5
+ }
widgets/contact/styles/default.less CHANGED
@@ -203,6 +203,10 @@
203
  lighten(@submit_background_color, @submit_background_gradient)
204
  );
205
  }
 
 
 
 
206
 
207
  border: @submit_border_width @submit_border_style @submit_border_color;
208
  border-radius: @submit_border_radius;
203
  lighten(@submit_background_color, @submit_background_gradient)
204
  );
205
  }
206
+
207
+ & when( @submit_background_gradient = 0% ) {
208
+ background: @submit_background_color;
209
+ }
210
 
211
  border: @submit_border_width @submit_border_style @submit_border_color;
212
  border-radius: @submit_border_radius;
widgets/editor/editor.php CHANGED
@@ -1,118 +1,119 @@
1
- <?php
2
-
3
- /*
4
- Widget Name: Editor
5
- Description: A widget which allows editing of content using the TinyMCE editor.
6
- Author: SiteOrigin
7
- Author URI: https://siteorigin.com
8
- */
9
-
10
- class SiteOrigin_Widget_Editor_Widget extends SiteOrigin_Widget {
11
-
12
- function __construct() {
13
-
14
- parent::__construct(
15
- 'sow-editor',
16
- __('SiteOrigin Editor', 'so-widgets-bundle'),
17
- array(
18
- 'description' => __('A rich-text, text editor.', 'so-widgets-bundle'),
19
- 'help' => 'https://siteorigin.com/widgets-bundle/editor-widget/'
20
- ),
21
- array(),
22
- false,
23
- plugin_dir_path(__FILE__)
24
- );
25
- }
26
-
27
- function get_widget_form() {
28
- $global_settings = $this->get_global_settings();
29
- return array(
30
- 'title' => array(
31
- 'type' => 'text',
32
- 'label' => __('Title', 'so-widgets-bundle'),
33
- ),
34
- 'text' => array(
35
- 'type' => 'tinymce',
36
- 'rows' => 20
37
- ),
38
- 'autop' => array(
39
- 'type' => 'checkbox',
40
- 'default' => $global_settings['autop_default'],
41
- 'label' => __( 'Automatically add paragraphs', 'so-widgets-bundle' ),
42
- ),
43
- );
44
- }
45
-
46
- function get_settings_form() {
47
- return array(
48
- 'autop_default' => array(
49
- 'type' => 'checkbox',
50
- 'default' => true,
51
- 'label' => __( 'Enable the "Automatically add paragraphs" setting by default.', 'so-widgets-bundle' ),
52
- ),
53
- );
54
- }
55
-
56
- function unwpautop($string) {
57
- $string = str_replace("<p>", "", $string);
58
- $string = str_replace(array("<br />", "<br>", "<br/>"), "\n", $string);
59
- $string = str_replace("</p>", "\n\n", $string);
60
-
61
- return $string;
62
- }
63
-
64
- public function get_template_variables( $instance, $args ) {
65
- $instance = wp_parse_args(
66
- $instance,
67
- array( 'text' => '' )
68
- );
69
-
70
- if (
71
- // Only run these parts if we're rendering for the frontend
72
- empty( $GLOBALS[ 'SITEORIGIN_PANELS_CACHE_RENDER' ] ) &&
73
- empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] )
74
- ) {
75
- $instance['text'] = $this->unwpautop( $instance['text'] );
76
-
77
- if (function_exists('wp_make_content_images_responsive')) {
78
- $instance['text'] = wp_make_content_images_responsive( $instance['text'] );
79
- }
80
-
81
- // Manual support for Jetpack Markdown module.
82
- if ( class_exists( 'WPCom_Markdown' ) &&
83
- Jetpack::is_module_active( 'markdown' ) &&
84
- $instance['text_selected_editor'] == 'html'
85
- ) {
86
- $markdown_parser = WPCom_Markdown::get_instance();
87
- $instance['text'] = $markdown_parser->transform( $instance['text'] );
88
- }
89
-
90
- // Run some known stuff
91
- if( ! empty( $GLOBALS['wp_embed'] ) ) {
92
- $instance['text'] = $GLOBALS['wp_embed']->run_shortcode( $instance['text'] );
93
- $instance['text'] = $GLOBALS['wp_embed']->autoembed( $instance['text'] );
94
- }
95
-
96
- $instance['text'] = apply_filters( 'widget_text', $instance['text'] );
97
-
98
- if( $instance['autop'] ) {
99
- $instance['text'] = wpautop( $instance['text'] );
100
- }
101
-
102
- $instance['text'] = do_shortcode( shortcode_unautop( $instance['text'] ) );
103
- }
104
-
105
-
106
- return array(
107
- 'text' => $instance['text'],
108
- );
109
- }
110
-
111
-
112
- function get_style_name($instance) {
113
- // We're not using a style
114
- return false;
115
- }
116
- }
117
-
118
- siteorigin_widget_register( 'sow-editor', __FILE__, 'SiteOrigin_Widget_Editor_Widget' );
 
1
+ <?php
2
+
3
+ /*
4
+ Widget Name: Editor
5
+ Description: A widget which allows editing of content using the TinyMCE editor.
6
+ Author: SiteOrigin
7
+ Author URI: https://siteorigin.com
8
+ */
9
+
10
+ class SiteOrigin_Widget_Editor_Widget extends SiteOrigin_Widget {
11
+
12
+ function __construct() {
13
+
14
+ parent::__construct(
15
+ 'sow-editor',
16
+ __('SiteOrigin Editor', 'so-widgets-bundle'),
17
+ array(
18
+ 'description' => __('A rich-text, text editor.', 'so-widgets-bundle'),
19
+ 'help' => 'https://siteorigin.com/widgets-bundle/editor-widget/'
20
+ ),
21
+ array(),
22
+ false,
23
+ plugin_dir_path(__FILE__)
24
+ );
25
+ }
26
+
27
+ function get_widget_form() {
28
+ $global_settings = $this->get_global_settings();
29
+ return array(
30
+ 'title' => array(
31
+ 'type' => 'text',
32
+ 'label' => __('Title', 'so-widgets-bundle'),
33
+ ),
34
+ 'text' => array(
35
+ 'type' => 'tinymce',
36
+ 'rows' => 20,
37
+ 'wpautop' => false, // Let the editor handle it's own processing.
38
+ ),
39
+ 'autop' => array(
40
+ 'type' => 'checkbox',
41
+ 'default' => $global_settings['autop_default'],
42
+ 'label' => __( 'Automatically add paragraphs', 'so-widgets-bundle' ),
43
+ ),
44
+ );
45
+ }
46
+
47
+ function get_settings_form() {
48
+ return array(
49
+ 'autop_default' => array(
50
+ 'type' => 'checkbox',
51
+ 'default' => true,
52
+ 'label' => __( 'Enable the "Automatically add paragraphs" setting by default.', 'so-widgets-bundle' ),
53
+ ),
54
+ );
55
+ }
56
+
57
+ function unwpautop($string) {
58
+ $string = str_replace("<p>", "", $string);
59
+ $string = str_replace(array("<br />", "<br>", "<br/>"), "\n", $string);
60
+ $string = str_replace("</p>", "\n\n", $string);
61
+
62
+ return $string;
63
+ }
64
+
65
+ public function get_template_variables( $instance, $args ) {
66
+ $instance = wp_parse_args(
67
+ $instance,
68
+ array( 'text' => '' )
69
+ );
70
+
71
+ if (
72
+ // Only run these parts if we're rendering for the frontend
73
+ empty( $GLOBALS[ 'SITEORIGIN_PANELS_CACHE_RENDER' ] ) &&
74
+ empty( $GLOBALS[ 'SITEORIGIN_PANELS_POST_CONTENT_RENDER' ] )
75
+ ) {
76
+ $instance['text'] = $this->unwpautop( $instance['text'] );
77
+
78
+ if (function_exists('wp_make_content_images_responsive')) {
79
+ $instance['text'] = wp_make_content_images_responsive( $instance['text'] );
80
+ }
81
+
82
+ // Manual support for Jetpack Markdown module.
83
+ if ( class_exists( 'WPCom_Markdown' ) &&
84
+ Jetpack::is_module_active( 'markdown' ) &&
85
+ $instance['text_selected_editor'] == 'html'
86
+ ) {
87
+ $markdown_parser = WPCom_Markdown::get_instance();
88
+ $instance['text'] = $markdown_parser->transform( $instance['text'] );
89
+ }
90
+
91
+ // Run some known stuff
92
+ if( ! empty( $GLOBALS['wp_embed'] ) ) {
93
+ $instance['text'] = $GLOBALS['wp_embed']->run_shortcode( $instance['text'] );
94
+ $instance['text'] = $GLOBALS['wp_embed']->autoembed( $instance['text'] );
95
+ }
96
+
97
+ $instance['text'] = apply_filters( 'widget_text', $instance['text'] );
98
+
99
+ if( $instance['autop'] ) {
100
+ $instance['text'] = wpautop( $instance['text'] );
101
+ }
102
+
103
+ $instance['text'] = do_shortcode( shortcode_unautop( $instance['text'] ) );
104
+ }
105
+
106
+
107
+ return array(
108
+ 'text' => $instance['text'],
109
+ );
110
+ }
111
+
112
+
113
+ function get_style_name($instance) {
114
+ // We're not using a style
115
+ return false;
116
+ }
117
+ }
118
+
119
+ siteorigin_widget_register( 'sow-editor', __FILE__, 'SiteOrigin_Widget_Editor_Widget' );
widgets/features/features.php CHANGED
@@ -278,6 +278,7 @@ class SiteOrigin_Widget_Features_Widget extends SiteOrigin_Widget {
278
 
279
  $less_vars['container_size'] = $instance['container_size'];
280
  $less_vars['icon_size'] = $instance['icon_size'];
 
281
  $less_vars['use_icon_size'] = empty( $instance['icon_size_custom'] ) ? 'false' : 'true';
282
 
283
  $global_settings = $this->get_global_settings();
278
 
279
  $less_vars['container_size'] = $instance['container_size'];
280
  $less_vars['icon_size'] = $instance['icon_size'];
281
+ $less_vars['per_row'] = $instance['per_row'];
282
  $less_vars['use_icon_size'] = empty( $instance['icon_size_custom'] ) ? 'false' : 'true';
283
 
284
  $global_settings = $this->get_global_settings();
widgets/features/styles/default.less CHANGED
@@ -16,6 +16,7 @@
16
  @more_text_font_weight: 400;
17
  @more_text_size: default;
18
  @more_text_color: default;
 
19
 
20
  @container_size: 84px;
21
  @icon_size: 24px;
@@ -24,9 +25,6 @@
24
  @responsive_breakpoint: 520px;
25
 
26
  .sow-features-list {
27
-
28
- margin: 0 -25px;
29
-
30
  .clearfix();
31
 
32
  .sow-features-feature {
@@ -36,6 +34,14 @@
36
  padding: 0 25px;
37
  display: flex;
38
 
 
 
 
 
 
 
 
 
39
  &.sow-icon-container-position-top {
40
  flex-direction: column;
41
  text-align: center;
16
  @more_text_font_weight: 400;
17
  @more_text_size: default;
18
  @more_text_color: default;
19
+ @per_row: 3;
20
 
21
  @container_size: 84px;
22
  @icon_size: 24px;
25
  @responsive_breakpoint: 520px;
26
 
27
  .sow-features-list {
 
 
 
28
  .clearfix();
29
 
30
  .sow-features-feature {
34
  padding: 0 25px;
35
  display: flex;
36
 
37
+ &:nth-of-type(@{per_row}n+1) {
38
+ padding-left: 0;
39
+ }
40
+
41
+ &:nth-of-type(@{per_row}n) {
42
+ padding-right: 0;
43
+ }
44
+
45
  &.sow-icon-container-position-top {
46
  flex-direction: column;
47
  text-align: center;
widgets/features/tpl/default.php CHANGED
@@ -1,69 +1,65 @@
1
- <?php
2
- $last_row = floor( ( count($instance['features']) - 1 ) / $instance['per_row'] );
3
- ?>
4
-
5
- <div class="sow-features-list <?php if( $instance['responsive'] ) echo 'sow-features-responsive'; ?>">
6
-
7
- <?php if( isset( $instance['features'] ) ) : ?>
8
- <?php foreach( $instance['features'] as $i => $feature ) : ?>
9
-
10
- <?php if( $i % $instance['per_row'] == 0 && $i != 0 ) : ?>
11
- <div class="sow-features-clear"></div>
12
- <?php endif; ?>
13
-
14
- <div class="sow-features-feature sow-icon-container-position-<?php echo esc_attr( $feature['container_position'] ) ?> <?php if( floor( $i / $instance['per_row'] ) == $last_row ) echo 'sow-features-feature-last-row' ?>" style="width: <?php echo round( 100 / $instance['per_row'], 3 ) ?>%">
15
-
16
- <?php if( !empty( $feature['more_url'] ) && $instance['icon_link'] ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
17
- <div
18
- class="sow-icon-container <?php echo !empty($instance['container_shape']) ? 'sow-container-' . esc_attr($instance['container_shape']) : 'sow-container-none'?>"
19
- style="color: <?php echo esc_attr($feature['container_color']) ?>; "
20
- <?php echo ( ! empty( $feature['icon_title'] ) ? 'title="' . esc_attr( $feature['icon_title'] ) . '"' : '' ); ?>>
21
- <?php
22
- $icon_styles = array();
23
- if( !empty($feature['icon_image']) ) {
24
- $size = empty( $feature['icon_image_size'] ) ? 'thumbnail' : $feature['icon_image_size'];
25
- $attachment = wp_get_attachment_image_src( $feature['icon_image'], $size );
26
- if(!empty($attachment)) {
27
- $icon_styles[] = 'background-image: url(' . sow_esc_url($attachment[0]) . ')';
28
- if(!empty($instance['icon_size'])) $icon_styles[] = 'font-size: '.intval($instance['icon_size']) . esc_attr( $instance['icon_size_unit'] );
29
-
30
- ?><div class="sow-icon-image" style="<?php echo implode('; ', $icon_styles) ?>"></div><?php
31
- }
32
- }
33
- else {
34
- if(!empty($instance['icon_size'])) $icon_styles[] = 'font-size: '.intval($instance['icon_size']).'px';
35
- if(!empty($feature['icon_color'])) $icon_styles[] = 'color: '.$feature['icon_color'];
36
-
37
- echo siteorigin_widget_get_icon($feature['icon'], $icon_styles);
38
- }
39
- ?>
40
- </div>
41
- <?php if( !empty( $feature['more_url'] ) && $instance['icon_link'] ) echo '</a>'; ?>
42
-
43
- <div class="textwidget">
44
- <?php if(!empty($feature['title'])) : ?>
45
- <h5>
46
- <?php if( !empty( $feature['more_url'] ) && $instance['title_link'] ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
47
- <?php echo wp_kses_post( $feature['title'] ) ?>
48
- <?php if( !empty( $feature['more_url'] ) && $instance['title_link'] ) echo '</a>'; ?>
49
- </h5>
50
- <?php endif; ?>
51
-
52
- <?php if(!empty($feature['text'])) : ?>
53
- <?php echo wp_kses_post( $feature['text'] ) ?>
54
- <?php endif; ?>
55
-
56
- <?php if(!empty($feature['more_text'])) : ?>
57
- <p class="sow-more-text">
58
- <?php if( !empty( $feature['more_url'] ) ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
59
- <?php echo wp_kses_post( $feature['more_text'] ) ?>
60
- <?php if( !empty( $feature['more_url'] ) ) echo '</a>'; ?>
61
- </p>
62
- <?php endif; ?>
63
- </div>
64
- </div>
65
-
66
- <?php endforeach; ?>
67
- <?php endif; ?>
68
-
69
- </div>
1
+ <?php
2
+ $last_row = floor( ( count($instance['features']) - 1 ) / $instance['per_row'] );
3
+ ?>
4
+
5
+ <div class="sow-features-list <?php if( $instance['responsive'] ) echo 'sow-features-responsive'; ?>">
6
+
7
+ <?php if( isset( $instance['features'] ) ) : ?>
8
+ <?php foreach( $instance['features'] as $i => $feature ) : ?>
9
+
10
+ <div class="sow-features-feature sow-icon-container-position-<?php echo esc_attr( $feature['container_position'] ) ?> <?php if( floor( $i / $instance['per_row'] ) == $last_row ) echo 'sow-features-feature-last-row' ?>" style="width: <?php echo round( 100 / $instance['per_row'], 3 ) ?>%">
11
+
12
+ <?php if( !empty( $feature['more_url'] ) && $instance['icon_link'] ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
13
+ <div
14
+ class="sow-icon-container <?php echo !empty($instance['container_shape']) ? 'sow-container-' . esc_attr($instance['container_shape']) : 'sow-container-none'?>"
15
+ style="color: <?php echo esc_attr($feature['container_color']) ?>; "
16
+ <?php echo ( ! empty( $feature['icon_title'] ) ? 'title="' . esc_attr( $feature['icon_title'] ) . '"' : '' ); ?>>
17
+ <?php
18
+ $icon_styles = array();
19
+ if( !empty($feature['icon_image']) ) {
20
+ $size = empty( $feature['icon_image_size'] ) ? 'thumbnail' : $feature['icon_image_size'];
21
+ $attachment = wp_get_attachment_image_src( $feature['icon_image'], $size );
22
+ if(!empty($attachment)) {
23
+ $icon_styles[] = 'background-image: url(' . sow_esc_url($attachment[0]) . ')';
24
+ if(!empty($instance['icon_size'])) $icon_styles[] = 'font-size: '.intval($instance['icon_size']) . esc_attr( $instance['icon_size_unit'] );
25
+
26
+ ?><div class="sow-icon-image" style="<?php echo implode('; ', $icon_styles) ?>"></div><?php
27
+ }
28
+ }
29
+ else {
30
+ if(!empty($instance['icon_size'])) $icon_styles[] = 'font-size: '.intval($instance['icon_size']).'px';
31
+ if(!empty($feature['icon_color'])) $icon_styles[] = 'color: '.$feature['icon_color'];
32
+
33
+ echo siteorigin_widget_get_icon($feature['icon'], $icon_styles);
34
+ }
35
+ ?>
36
+ </div>
37
+ <?php if( !empty( $feature['more_url'] ) && $instance['icon_link'] ) echo '</a>'; ?>
38
+
39
+ <div class="textwidget">
40
+ <?php if(!empty($feature['title'])) : ?>
41
+ <h5>
42
+ <?php if( !empty( $feature['more_url'] ) && $instance['title_link'] ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
43
+ <?php echo wp_kses_post( $feature['title'] ) ?>
44
+ <?php if( !empty( $feature['more_url'] ) && $instance['title_link'] ) echo '</a>'; ?>
45
+ </h5>
46
+ <?php endif; ?>
47
+
48
+ <?php if(!empty($feature['text'])) : ?>
49
+ <?php echo wp_kses_post( $feature['text'] ) ?>
50
+ <?php endif; ?>
51
+
52
+ <?php if(!empty($feature['more_text'])) : ?>
53
+ <p class="sow-more-text">
54
+ <?php if( !empty( $feature['more_url'] ) ) echo '<a href="' . sow_esc_url( $feature['more_url'] ) . '" ' . ( $instance['new_window'] ? 'target="_blank" rel="noopener noreferrer"' : '' ) . '>'; ?>
55
+ <?php echo wp_kses_post( $feature['more_text'] ) ?>
56
+ <?php if( !empty( $feature['more_url'] ) ) echo '</a>'; ?>
57
+ </p>
58
+ <?php endif; ?>
59
+ </div>
60
+ </div>
61
+
62
+ <?php endforeach; ?>
63
+ <?php endif; ?>
64
+
65
+ </div>
 
 
 
 
widgets/headline/headline.php CHANGED
@@ -1,419 +1,419 @@
1
- <?php
2
-
3
- /*
4
- Widget Name: Headline
5
- Description: A headline to headline all headlines.
6
- Author: SiteOrigin
7
- Author URI: https://siteorigin.com
8
- */
9
-
10
- class SiteOrigin_Widget_Headline_Widget extends SiteOrigin_Widget {
11
-
12
- function __construct() {
13
-
14
- parent::__construct(
15
- 'sow-headline',
16
- __( 'SiteOrigin Headline', 'so-widgets-bundle' ),
17
- array(
18
- 'description' => __( 'A headline widget.', 'so-widgets-bundle' )
19
- ),
20
- array(),
21
- false,
22
- plugin_dir_path(__FILE__)
23
- );
24
- }
25
-
26
- function initialize(){
27
- add_filter( 'siteorigin_widgets_wrapper_classes_' . $this->id_base, array( $this, 'wrapper_class_filter' ), 10, 2 );
28
- add_filter( 'siteorigin_widgets_wrapper_data_' . $this->id_base, array( $this, 'wrapper_data_filter' ), 10, 2 );
29
- }
30
-
31
- function get_widget_form(){
32
- return array(
33
- 'headline' => array(
34
- 'type' => 'section',
35
- 'label' => __( 'Headline', 'so-widgets-bundle' ),
36
- 'hide' => false,
37
- 'fields' => array(
38
- 'text' => array(
39
- 'type' => 'text',
40
- 'label' => __( 'Text', 'so-widgets-bundle' ),
41
- ),
42
- 'destination_url' => array(
43
- 'type' => 'link',
44
- 'label' => __( 'Destination URL', 'so-widgets-bundle' ),
45
- ),
46
- 'new_window' => array(
47
- 'type' => 'checkbox',
48
- 'default' => false,
49
- 'label' => __( 'Open in a new window', 'so-widgets-bundle' ),
50
- ),
51
- 'tag' => array(
52
- 'type' => 'select',
53
- 'label' => __( 'HTML Tag', 'so-widgets-bundle' ),
54
- 'default' => 'h1',
55
- 'options' => array(
56
- 'h1' => __( 'H1', 'so-widgets-bundle' ),
57
- 'h2' => __( 'H2', 'so-widgets-bundle' ),
58
- 'h3' => __( 'H3', 'so-widgets-bundle' ),
59
- 'h4' => __( 'H4', 'so-widgets-bundle' ),
60
- 'h5' => __( 'H5', 'so-widgets-bundle' ),
61
- 'h6' => __( 'H6', 'so-widgets-bundle' ),
62
- 'p' => __( 'Paragraph', 'so-widgets-bundle' ),
63
- )
64
- ),
65
- 'color' => array(
66
- 'type' => 'color',
67
- 'label' => __('Color', 'so-widgets-bundle'),
68
- ),
69
- 'hover_color' => array(
70
- 'type' => 'color',
71
- 'label' => __('Hover Color', 'so-widgets-bundle'),
72
- ),
73
- 'font' => array(
74
- 'type' => 'font',
75
- 'label' => __( 'Font', 'so-widgets-bundle' ),
76
- 'default' => 'default'
77
- ),
78
- 'font_size' => array(
79
- 'type' => 'measurement',
80
- 'label' => __('Font Size', 'so-widgets-bundle')
81
- ),
82
- 'align' => array(
83
- 'type' => 'select',
84
- 'label' => __( 'Alignment', 'so-widgets-bundle' ),
85
- 'default' => 'center',
86
- 'options' => array(
87
- 'center' => __( 'Center', 'so-widgets-bundle' ),
88
- 'left' => __( 'Left', 'so-widgets-bundle' ),
89
- 'right' => __( 'Right', 'so-widgets-bundle' ),
90
- 'justify' => __( 'Justify', 'so-widgets-bundle' )
91
- )
92
- ),
93
- 'line_height' => array(
94
- 'type' => 'measurement',
95
- 'label' => __('Line Height', 'so-widgets-bundle')
96
- ),
97
- 'margin' => array(
98
- 'type' => 'measurement',
99
- 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
100
- 'default' => '',
101
- ),
102
- )
103
- ),
104
- 'sub_headline' => array(
105
- 'type' => 'section',
106
- 'label' => __( 'Sub headline', 'so-widgets-bundle' ),
107
- 'hide' => true,
108
- 'fields' => array(
109
- 'text' => array(
110
- 'type' => 'text',
111
- 'label' => __('Text', 'so-widgets-bundle')
112
- ),
113
- 'destination_url' => array(
114
- 'type' => 'link',
115
- 'label' => __( 'Destination URL', 'so-widgets-bundle' ),
116
- ),
117
- 'new_window' => array(
118
- 'type' => 'checkbox',
119
- 'default' => false,
120
- 'label' => __( 'Open in a new window', 'so-widgets-bundle' ),
121
- ),
122
- 'tag' => array(
123
- 'type' => 'select',
124
- 'label' => __( 'HTML Tag', 'so-widgets-bundle' ),
125
- 'default' => 'h3',
126
- 'options' => array(
127
- 'h1' => __( 'H1', 'so-widgets-bundle' ),
128
- 'h2' => __( 'H2', 'so-widgets-bundle' ),
129
- 'h3' => __( 'H3', 'so-widgets-bundle' ),
130
- 'h4' => __( 'H4', 'so-widgets-bundle' ),
131
- 'h5' => __( 'H5', 'so-widgets-bundle' ),
132
- 'h6' => __( 'H6', 'so-widgets-bundle' ),
133
- 'p' => __( 'Paragraph', 'so-widgets-bundle' ),
134
- )
135
- ),
136
- 'color' => array(
137
- 'type' => 'color',
138
- 'label' => __('Color', 'so-widgets-bundle'),
139
- ),
140
- 'hover_color' => array(
141
- 'type' => 'color',
142
- 'label' => __('Hover Color', 'so-widgets-bundle'),
143
- ),
144
- 'font' => array(
145
- 'type' => 'font',
146
- 'label' => __( 'Font', 'so-widgets-bundle' ),
147
- 'default' => 'default'
148
- ),
149
- 'font_size' => array(
150
- 'type' => 'measurement',
151
- 'label' => __('Font Size', 'so-widgets-bundle')
152
- ),
153
- 'align' => array(
154
- 'type' => 'select',
155
- 'label' => __( 'Alignment', 'so-widgets-bundle' ),
156
- 'default' => 'center',
157
- 'options' => array(
158
- 'center' => __( 'Center', 'so-widgets-bundle' ),
159
- 'left' => __( 'Left', 'so-widgets-bundle' ),
160
- 'right' => __( 'Right', 'so-widgets-bundle' ),
161
- 'justify' => __( 'Justify', 'so-widgets-bundle' )
162
- )
163
- ),
164
- 'line_height' => array(
165
- 'type' => 'measurement',
166
- 'label' => __('Line Height', 'so-widgets-bundle')
167
- ),
168
- 'margin' => array(
169
- 'type' => 'measurement',
170
- 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
171
- 'default' => '',
172
- ),
173
- )
174
- ),
175
- 'divider' => array(
176
- 'type' => 'section',
177
- 'label' => __( 'Divider', 'so-widgets-bundle' ),
178
- 'hide' => true,
179
- 'fields' => array(
180
- 'style' => array(
181
- 'type' => 'select',
182
- 'label' => __( 'Style', 'so-widgets-bundle' ),
183
- 'default' => 'solid',
184
- 'options' => array(
185
- 'none' => __('None', 'so-widgets-bundle'),
186
- 'solid' => __('Solid', 'so-widgets-bundle'),
187
- 'dotted' => __('Dotted', 'so-widgets-bundle'),
188
- 'dashed' => __('Dashed', 'so-widgets-bundle'),
189
- 'double' => __('Double', 'so-widgets-bundle'),
190
- 'groove' => __('Groove', 'so-widgets-bundle'),
191
- 'ridge' => __('Ridge', 'so-widgets-bundle'),
192
- 'inset' => __('Inset', 'so-widgets-bundle'),
193
- 'outset' => __('Outset', 'so-widgets-bundle'),
194
- )
195
- ),
196
- 'color' => array(
197
- 'type' => 'color',
198
- 'label' => __('Color', 'so-widgets-bundle'),
199
- 'default' => '#EEEEEE'
200
- ),
201
- 'thickness' => array(
202
- 'type' => 'slider',
203
- 'label' => __( 'Thickness', 'so-widgets-bundle' ),
204
- 'min' => 0,
205
- 'max' => 20,
206
- 'default' => 1
207
- ),
208
- 'align' => array(
209
- 'type' => 'select',
210
- 'label' => __('Alignment', 'so-widgets-bundle'),
211
- 'default' => 'center',
212
- 'options' => array(
213
- 'center' => __( 'Center', 'so-widgets-bundle' ),
214
- 'left' => __( 'Left', 'so-widgets-bundle' ),
215
- 'right' => __( 'Right', 'so-widgets-bundle' ),
216
- ),
217
- ),
218
- 'width' => array(
219
- 'type' => 'measurement',
220
- 'label' => __('Divider Width', 'so-widgets-bundle'),
221
- 'default' => '80%',
222
- ),
223
- 'margin' => array(
224
- 'type' => 'measurement',
225
- 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
226
- 'default' => '',
227
- ),
228
- )
229
- ),
230
-
231
- 'order' => array(
232
- 'type' => 'order',
233
- 'label' => __( 'Element Order', 'so-widgets-bundle' ),
234
- 'options' => array(
235
- 'headline' => __( 'Headline', 'so-widgets-bundle' ),
236
- 'divider' => __( 'Divider', 'so-widgets-bundle' ),
237
- 'sub_headline' => __( 'Sub Headline', 'so-widgets-bundle' ),
238
- ),
239
- 'default' => array( 'headline', 'divider', 'sub_headline' ),
240
- ),
241
-
242
- 'fittext' => array(
243
- 'type' => 'checkbox',
244
- 'label' => __( 'Use FitText', 'so-widgets-bundle' ),
245
- 'description' => __( 'Dynamically adjust your heading font size based on screen size.', 'so-widgets-bundle' ),
246
- 'default' => false,
247
- 'state_emitter' => array(
248
- 'callback' => 'conditional',
249
- 'args' => array(
250
- 'use_fittext[show]: val',
251
- 'use_fittext[hide]: ! val'
252
- ),
253
- )
254
- ),
255
-
256
- 'fittext_compressor' => array(
257
- 'type' => 'number',
258
- 'label' => __( 'FitText Compressor Strength', 'so-widgets-bundle' ),
259
- 'description' => __( 'How aggressively FitText should resize your heading.', 'so-widgets-bundle' ),
260
- 'default' => 0.85,
261
- 'state_handler' => array(
262
- 'use_fittext[show]' => array( 'show' ),
263
- 'use_fittext[hide]' => array( 'hide' ),
264
- )
265
- ),
266
- );
267
- }
268
-
269
- function get_less_variables( $instance ) {
270
- $less_vars = array();
271
-
272
- // All the headline attributes
273
- $less_vars['headline_tag'] = isset( $instance['headline']['tag'] ) ? $instance['headline']['tag'] : false;
274
- $less_vars['headline_hover_color'] = isset( $instance['headline']['hover_color'] ) ? $instance['headline']['hover_color'] : false;
275
- $less_vars['headline_align'] = isset( $instance['headline']['align'] ) ? $instance['headline']['align'] : false;
276
- $less_vars['headline_color'] = isset( $instance['headline']['color'] ) ? $instance['headline']['color'] : false;
277
- $less_vars['headline_font_size'] = isset( $instance['headline']['font_size'] ) ? $instance['headline']['font_size'] : false;
278
- $less_vars['headline_line_height'] = isset( $instance['headline']['line_height'] ) ? $instance['headline']['line_height'] : false;
279
- $less_vars['headline_margin'] = isset( $instance['headline']['margin'] ) ? $instance['headline']['margin'] : false;
280
-
281
- // Headline font family and weight
282
- if ( ! empty( $instance['headline']['font'] ) ) {
283
- $font = siteorigin_widget_get_font( $instance['headline']['font'] );
284
- $less_vars['headline_font'] = $font['family'];
285
- if ( ! empty( $font['weight'] ) ) {
286
- $less_vars['headline_font_weight'] = $font['weight'];
287
- }
288
- }
289
-
290
- // Set the sub headline attributes
291
- $less_vars['sub_headline_align'] = isset( $instance['sub_headline']['align'] ) ? $instance['sub_headline']['align'] : false;
292
- $less_vars['sub_headline_hover_color'] = isset( $instance['sub_headline']['hover_color'] ) ? $instance['sub_headline']['hover_color'] : false;
293
- $less_vars['sub_headline_tag'] = isset( $instance['sub_headline']['tag'] ) ? $instance['sub_headline']['tag'] : false;
294
- $less_vars['sub_headline_color'] = isset( $instance['sub_headline']['color'] ) ? $instance['sub_headline']['color'] : false;
295
- $less_vars['sub_headline_font_size'] = isset( $instance['sub_headline']['font_size'] ) ? $instance['sub_headline']['font_size'] : false;
296
- $less_vars['sub_headline_line_height'] = isset( $instance['sub_headline']['line_height'] ) ? $instance['sub_headline']['line_height'] : false;
297
- $less_vars['sub_headline_margin'] = isset( $instance['sub_headline']['margin'] ) ? $instance['sub_headline']['margin'] : false;
298
-
299
- // Sub headline font family and weight
300
- if ( ! empty( $instance['sub_headline']['font'] ) ) {
301
- $font = siteorigin_widget_get_font( $instance['sub_headline']['font'] );
302
- $less_vars['sub_headline_font'] = $font['family'];
303
- if ( ! empty( $font['weight'] ) ) {
304
- $less_vars['sub_headline_font_weight'] = $font['weight'];
305
- }
306
- }
307
-
308
- $less_vars['divider_style'] = isset( $instance['divider']['style'] ) ? $instance['divider']['style'] : false;
309
- $less_vars['divider_width'] = isset( $instance['divider']['width'] ) ? $instance['divider']['width'] : false;
310
- $less_vars['divider_thickness'] = isset( $instance['divider']['thickness'] ) ? intval( $instance['divider']['thickness'] ) . 'px' : false;
311
- $less_vars['divider_align'] = isset( $instance['divider']['align'] ) ? $instance['divider']['align'] : false;
312
- $less_vars['divider_color'] = isset( $instance['divider']['color'] ) ? $instance['divider']['color'] : false;
313
- $less_vars['divider_margin'] = isset( $instance['divider']['margin'] ) ? $instance['divider']['margin'] : false;
314
-
315
- return $less_vars;
316
- }
317
-
318
- function get_google_font_fields( $instance ) {
319
- return array(
320
- $instance['headline']['font'],
321
- $instance['sub_headline']['font'],
322
- );
323
- }
324
-
325
- /**
326
- * Get the template variables for the headline
327
- *
328
- * @param $instance
329
- * @param $args
330
- *
331
- * @return array
332
- */
333
- function get_template_variables( $instance, $args ) {
334
- if( empty( $instance ) ) return array();
335
-
336
- return array(
337
- 'headline' => $instance['headline']['text'],
338
- 'headline_destination_url' => $instance['headline']['destination_url'],
339
- 'headline_new_window' => $instance['headline']['new_window'],
340
- 'headline_tag' => $instance['headline']['tag'],
341
- 'sub_headline' => $instance['sub_headline']['text'],
342
- 'sub_headline_destination_url' => $instance['sub_headline']['destination_url'],
343
- 'sub_headline_new_window' => $instance['sub_headline']['new_window'],
344
- 'sub_headline_tag' => $instance['sub_headline']['tag'],
345
- 'order' => $instance['order'],
346
- 'has_divider' => ! empty( $instance['divider'] ) && $instance['divider']['style'] != 'none'
347
- );
348
- }
349
-
350
- function wrapper_class_filter( $classes, $instance ){
351
- if( $instance[ 'fittext' ] ) {
352
- $classes[] = 'so-widget-fittext-wrapper';
353
- wp_enqueue_script( 'sow-fittext' );
354
- }
355
- return $classes;
356
- }
357
-
358
- function wrapper_data_filter( $data, $instance ) {
359
- if( $instance['fittext'] ) {
360
- $data['fit-text-compressor'] = $instance['fittext_compressor'];
361
- }
362
- return $data;
363
- }
364
-
365
- function modify_instance( $instance ) {
366
- // Change the old divider weight into a divider thickness
367
- if( isset( $instance['divider']['weight'] ) && ! isset( $instance['divider']['thickness'] ) ) {
368
- switch( $instance['divider']['weight'] ) {
369
- case 'medium':
370
- $instance['divider']['thickness'] = 3;
371
- break;
372
- case 'thick':
373
- $instance['divider']['thickness'] = 5;
374
- break;
375
- case 'thin' :
376
- default :
377
- $instance['divider']['thickness'] = 1;
378
- break;
379
- }
380
- unset( $instance['divider']['weight'] );
381
- }
382
-
383
- // Change the old divider side margin into overall width
384
- if( isset( $instance['divider']['side_margin'] ) && ! isset( $instance['divider']['width'] ) ) {
385
- global $content_width;
386
- $value = floatval( $instance['divider']['side_margin'] );
387
-
388
- switch( $instance['divider']['side_margin_unit'] ) {
389
- case 'px' :
390
- $instance['divider']['width'] = ( ( !empty( $content_width ) ? $content_width : 960 ) - ( 2 * $value ) ) . 'px';
391
- $instance['divider']['width_unit'] = 'px';
392
- break;
393
-
394
- case '%' :
395
- $instance['divider']['width'] = ( 100 - (2 * $value) ) . '%';
396
- $instance['divider']['width_unit'] = '%';
397
- break;
398
-
399
- default :
400
- $instance['divider']['width'] = '80%';
401
- $instance['divider']['width_unit'] = '%';
402
- break;
403
- }
404
-
405
- unset( $instance['divider']['side_margin'] );
406
- unset( $instance['divider']['side_margin_unit'] );
407
- }
408
-
409
- // Copy top margin over to bottom margin
410
- if( isset( $instance['divider']['top_margin'] ) && ! isset( $instance['divider']['bottom_margin'] ) ) {
411
- $instance['divider']['bottom_margin'] = $instance['divider']['top_margin'];
412
- $instance['divider']['bottom_margin_unit'] = $instance['divider']['top_margin_unit'];
413
- }
414
-
415
- return $instance;
416
- }
417
- }
418
-
419
- siteorigin_widget_register('sow-headline', __FILE__, 'SiteOrigin_Widget_Headline_Widget');
1
+ <?php
2
+
3
+ /*
4
+ Widget Name: Headline
5
+ Description: A headline to headline all headlines.
6
+ Author: SiteOrigin
7
+ Author URI: https://siteorigin.com
8
+ */
9
+
10
+ class SiteOrigin_Widget_Headline_Widget extends SiteOrigin_Widget {
11
+
12
+ function __construct() {
13
+
14
+ parent::__construct(
15
+ 'sow-headline',
16
+ __( 'SiteOrigin Headline', 'so-widgets-bundle' ),
17
+ array(
18
+ 'description' => __( 'A headline widget.', 'so-widgets-bundle' )
19
+ ),
20
+ array(),
21
+ false,
22
+ plugin_dir_path(__FILE__)
23
+ );
24
+ }
25
+
26
+ function initialize(){
27
+ add_filter( 'siteorigin_widgets_wrapper_classes_' . $this->id_base, array( $this, 'wrapper_class_filter' ), 10, 2 );
28
+ add_filter( 'siteorigin_widgets_wrapper_data_' . $this->id_base, array( $this, 'wrapper_data_filter' ), 10, 2 );
29
+ }
30
+
31
+ function get_widget_form(){
32
+ return array(
33
+ 'headline' => array(
34
+ 'type' => 'section',
35
+ 'label' => __( 'Headline', 'so-widgets-bundle' ),
36
+ 'hide' => false,
37
+ 'fields' => array(
38
+ 'text' => array(
39
+ 'type' => 'text',
40
+ 'label' => __( 'Text', 'so-widgets-bundle' ),
41
+ ),
42
+ 'destination_url' => array(
43
+ 'type' => 'link',
44
+ 'label' => __( 'Destination URL', 'so-widgets-bundle' ),
45
+ ),
46
+ 'new_window' => array(
47
+ 'type' => 'checkbox',
48
+ 'default' => false,
49
+ 'label' => __( 'Open in a new window', 'so-widgets-bundle' ),
50
+ ),
51
+ 'tag' => array(
52
+ 'type' => 'select',
53
+ 'label' => __( 'HTML Tag', 'so-widgets-bundle' ),
54
+ 'default' => 'h1',
55
+ 'options' => array(
56
+ 'h1' => __( 'H1', 'so-widgets-bundle' ),
57
+ 'h2' => __( 'H2', 'so-widgets-bundle' ),
58
+ 'h3' => __( 'H3', 'so-widgets-bundle' ),
59
+ 'h4' => __( 'H4', 'so-widgets-bundle' ),
60
+ 'h5' => __( 'H5', 'so-widgets-bundle' ),
61
+ 'h6' => __( 'H6', 'so-widgets-bundle' ),
62
+ 'p' => __( 'Paragraph', 'so-widgets-bundle' ),
63
+ )
64
+ ),
65
+ 'color' => array(
66
+ 'type' => 'color',
67
+ 'label' => __('Color', 'so-widgets-bundle'),
68
+ ),
69
+ 'hover_color' => array(
70
+ 'type' => 'color',
71
+ 'label' => __('Hover Color', 'so-widgets-bundle'),
72
+ ),
73
+ 'font' => array(
74
+ 'type' => 'font',
75
+ 'label' => __( 'Font', 'so-widgets-bundle' ),
76
+ 'default' => 'default'
77
+ ),
78
+ 'font_size' => array(
79
+ 'type' => 'measurement',
80
+ 'label' => __('Font Size', 'so-widgets-bundle')
81
+ ),
82
+ 'align' => array(
83
+ 'type' => 'select',
84
+ 'label' => __( 'Alignment', 'so-widgets-bundle' ),
85
+ 'default' => 'center',
86
+ 'options' => array(
87
+ 'center' => __( 'Center', 'so-widgets-bundle' ),
88
+ 'left' => __( 'Left', 'so-widgets-bundle' ),
89
+ 'right' => __( 'Right', 'so-widgets-bundle' ),
90
+ 'justify' => __( 'Justify', 'so-widgets-bundle' )
91
+ )
92
+ ),
93
+ 'line_height' => array(
94
+ 'type' => 'measurement',
95
+ 'label' => __('Line Height', 'so-widgets-bundle')
96
+ ),
97
+ 'margin' => array(
98
+ 'type' => 'measurement',
99
+ 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
100
+ 'default' => '',
101
+ ),
102
+ )
103
+ ),
104
+ 'sub_headline' => array(
105
+ 'type' => 'section',
106
+ 'label' => __( 'Sub headline', 'so-widgets-bundle' ),
107
+ 'hide' => true,
108
+ 'fields' => array(
109
+ 'text' => array(
110
+ 'type' => 'text',
111
+ 'label' => __('Text', 'so-widgets-bundle')
112
+ ),
113
+ 'destination_url' => array(
114
+ 'type' => 'link',
115
+ 'label' => __( 'Destination URL', 'so-widgets-bundle' ),
116
+ ),
117
+ 'new_window' => array(
118
+ 'type' => 'checkbox',
119
+ 'default' => false,
120
+ 'label' => __( 'Open in a new window', 'so-widgets-bundle' ),
121
+ ),
122
+ 'tag' => array(
123
+ 'type' => 'select',
124
+ 'label' => __( 'HTML Tag', 'so-widgets-bundle' ),
125
+ 'default' => 'h3',
126
+ 'options' => array(
127
+ 'h1' => __( 'H1', 'so-widgets-bundle' ),
128
+ 'h2' => __( 'H2', 'so-widgets-bundle' ),
129
+ 'h3' => __( 'H3', 'so-widgets-bundle' ),
130
+ 'h4' => __( 'H4', 'so-widgets-bundle' ),
131
+ 'h5' => __( 'H5', 'so-widgets-bundle' ),
132
+ 'h6' => __( 'H6', 'so-widgets-bundle' ),
133
+ 'p' => __( 'Paragraph', 'so-widgets-bundle' ),
134
+ )
135
+ ),
136
+ 'color' => array(
137
+ 'type' => 'color',
138
+ 'label' => __('Color', 'so-widgets-bundle'),
139
+ ),
140
+ 'hover_color' => array(
141
+ 'type' => 'color',
142
+ 'label' => __('Hover Color', 'so-widgets-bundle'),
143
+ ),
144
+ 'font' => array(
145
+ 'type' => 'font',
146
+ 'label' => __( 'Font', 'so-widgets-bundle' ),
147
+ 'default' => 'default'
148
+ ),
149
+ 'font_size' => array(
150
+ 'type' => 'measurement',
151
+ 'label' => __('Font Size', 'so-widgets-bundle')
152
+ ),
153
+ 'align' => array(
154
+ 'type' => 'select',
155
+ 'label' => __( 'Alignment', 'so-widgets-bundle' ),
156
+ 'default' => 'center',
157
+ 'options' => array(
158
+ 'center' => __( 'Center', 'so-widgets-bundle' ),
159
+ 'left' => __( 'Left', 'so-widgets-bundle' ),
160
+ 'right' => __( 'Right', 'so-widgets-bundle' ),
161
+ 'justify' => __( 'Justify', 'so-widgets-bundle' )
162
+ )
163
+ ),
164
+ 'line_height' => array(
165
+ 'type' => 'measurement',
166
+ 'label' => __('Line Height', 'so-widgets-bundle')
167
+ ),
168
+ 'margin' => array(
169
+ 'type' => 'measurement',
170
+ 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
171
+ 'default' => '',
172
+ ),
173
+ )
174
+ ),
175
+ 'divider' => array(
176
+ 'type' => 'section',
177
+ 'label' => __( 'Divider', 'so-widgets-bundle' ),
178
+ 'hide' => true,
179
+ 'fields' => array(
180
+ 'style' => array(
181
+ 'type' => 'select',
182
+ 'label' => __( 'Style', 'so-widgets-bundle' ),
183
+ 'default' => 'solid',
184
+ 'options' => array(
185
+ 'none' => __('None', 'so-widgets-bundle'),
186
+ 'solid' => __('Solid', 'so-widgets-bundle'),
187
+ 'dotted' => __('Dotted', 'so-widgets-bundle'),
188
+ 'dashed' => __('Dashed', 'so-widgets-bundle'),
189
+ 'double' => __('Double', 'so-widgets-bundle'),
190
+ 'groove' => __('Groove', 'so-widgets-bundle'),
191
+ 'ridge' => __('Ridge', 'so-widgets-bundle'),
192
+ 'inset' => __('Inset', 'so-widgets-bundle'),
193
+ 'outset' => __('Outset', 'so-widgets-bundle'),
194
+ )
195
+ ),
196
+ 'color' => array(
197
+ 'type' => 'color',
198
+ 'label' => __('Color', 'so-widgets-bundle'),
199
+ 'default' => '#EEEEEE'
200
+ ),
201
+ 'thickness' => array(
202
+ 'type' => 'slider',
203
+ 'label' => __( 'Thickness', 'so-widgets-bundle' ),
204
+ 'min' => 0,
205
+ 'max' => 20,
206
+ 'default' => 1
207
+ ),
208
+ 'align' => array(
209
+ 'type' => 'select',
210
+ 'label' => __('Alignment', 'so-widgets-bundle'),
211
+ 'default' => 'center',
212
+ 'options' => array(
213
+ 'center' => __( 'Center', 'so-widgets-bundle' ),
214
+ 'left' => __( 'Left', 'so-widgets-bundle' ),
215
+ 'right' => __( 'Right', 'so-widgets-bundle' ),
216
+ ),
217
+ ),
218
+ 'width' => array(
219
+ 'type' => 'measurement',
220
+ 'label' => __('Divider Width', 'so-widgets-bundle'),
221
+ 'default' => '80%',
222
+ ),
223
+ 'margin' => array(
224
+ 'type' => 'measurement',
225
+ 'label' => __('Top and Bottom Margin', 'so-widgets-bundle'),
226
+ 'default' => '',
227
+ ),
228
+ )
229
+ ),
230
+
231
+ 'order' => array(
232
+ 'type' => 'order',
233
+ 'label' => __( 'Element Order', 'so-widgets-bundle' ),
234
+ 'options' => array(
235
+ 'headline' => __( 'Headline', 'so-widgets-bundle' ),
236
+ 'divider' => __( 'Divider', 'so-widgets-bundle' ),
237
+ 'sub_headline' => __( 'Sub Headline', 'so-widgets-bundle' ),
238
+ ),
239
+ 'default' => array( 'headline', 'divider', 'sub_headline' ),
240
+ ),
241
+
242
+ 'fittext' => array(
243
+ 'type' => 'checkbox',
244
+ 'label' => __( 'Use FitText', 'so-widgets-bundle' ),
245
+ 'description' => __( 'Dynamically adjust your heading font size based on screen size.', 'so-widgets-bundle' ),
246
+ 'default' => false,
247
+ 'state_emitter' => array(
248
+ 'callback' => 'conditional',
249
+ 'args' => array(
250
+ 'use_fittext[show]: val',
251
+ 'use_fittext[hide]: ! val'
252
+ ),
253
+ )
254
+ ),
255
+
256
+ 'fittext_compressor' => array(
257
+ 'type' => 'number',
258
+ 'label' => __( 'FitText Compressor Strength', 'so-widgets-bundle' ),
259
+ 'description' => __( 'How aggressively FitText should resize your heading.', 'so-widgets-bundle' ),
260
+ 'default' => 0.85,
261
+ 'state_handler' => array(
262
+ 'use_fittext[show]' => array( 'show' ),
263
+ 'use_fittext[hide]' => array( 'hide' ),
264
+ )
265
+ ),
266
+ );
267
+ }
268
+
269
+ function get_less_variables( $instance ) {
270
+ $less_vars = array();
271
+
272
+ // All the headline attributes
273
+ $less_vars['headline_tag'] = isset( $instance['headline']['tag'] ) ? $instance['headline']['tag'] : false;
274
+ $less_vars['headline_hover_color'] = isset( $instance['headline']['hover_color'] ) ? $instance['headline']['hover_color'] : false;
275
+ $less_vars['headline_align'] = isset( $instance['headline']['align'] ) ? $instance['headline']['align'] : false;
276
+ $less_vars['headline_color'] = isset( $instance['headline']['color'] ) ? $instance['headline']['color'] : false;
277
+ $less_vars['headline_font_size'] = isset( $instance['headline']['font_size'] ) ? $instance['headline']['font_size'] : false;
278
+ $less_vars['headline_line_height'] = isset( $instance['headline']['line_height'] ) ? $instance['headline']['line_height'] : false;
279
+ $less_vars['headline_margin'] = isset( $instance['headline']['margin'] ) ? $instance['headline']['margin'] : false;
280
+
281
+ // Headline font family and weight
282
+ if ( ! empty( $instance['headline']['font'] ) ) {
283
+ $font = siteorigin_widget_get_font( $instance['headline']['font'] );
284
+ $less_vars['headline_font'] = $font['family'];
285
+ if ( ! empty( $font['weight'] ) ) {
286
+ $less_vars['headline_font_weight'] = $font['weight'];
287
+ }
288
+ }
289
+
290
+ // Set the sub headline attributes
291
+ $less_vars['sub_headline_align'] = isset( $instance['sub_headline']['align'] ) ? $instance['sub_headline']['align'] : false;
292
+ $less_vars['sub_headline_hover_color'] = isset( $instance['sub_headline']['hover_color'] ) ? $instance['sub_headline']['hover_color'] : false;
293
+ $less_vars['sub_headline_tag'] = isset( $instance['sub_headline']['tag'] ) ? $instance['sub_headline']['tag'] : false;
294
+ $less_vars['sub_headline_color'] = isset( $instance['sub_headline']['color'] ) ? $instance['sub_headline']['color'] : false;
295
+ $less_vars['sub_headline_font_size'] = isset( $instance['sub_headline']['font_size'] ) ? $instance['sub_headline']['font_size'] : false;
296
+ $less_vars['sub_headline_line_height'] = isset( $instance['sub_headline']['line_height'] ) ? $instance['sub_headline']['line_height'] : false;
297
+ $less_vars['sub_headline_margin'] = isset( $instance['sub_headline']['margin'] ) ? $instance['sub_headline']['margin'] : false;
298
+
299
+ // Sub headline font family and weight
300
+ if ( ! empty( $instance['sub_headline']['font'] ) ) {
301
+ $font = siteorigin_widget_get_font( $instance['sub_headline']['font'] );
302
+ $less_vars['sub_headline_font'] = $font['family'];
303
+ if ( ! empty( $font['weight'] ) ) {
304
+ $less_vars['sub_headline_font_weight'] = $font['weight'];
305
+ }
306
+ }
307
+
308
+ $less_vars['divider_style'] = isset( $instance['divider']['style'] ) ? $instance['divider']['style'] : false;
309
+ $less_vars['divider_width'] = isset( $instance['divider']['width'] ) ? $instance['divider']['width'] : false;
310
+ $less_vars['divider_thickness'] = isset( $instance['divider']['thickness'] ) ? intval( $instance['divider']['thickness'] ) . 'px' : false;
311
+ $less_vars['divider_align'] = isset( $instance['divider']['align'] ) ? $instance['divider']['align'] : false;
312
+ $less_vars['divider_color'] = isset( $instance['divider']['color'] ) ? $instance['divider']['color'] : false;
313
+ $less_vars['divider_margin'] = isset( $instance['divider']['margin'] ) ? $instance['divider']['margin'] : false;
314
+
315
+ return $less_vars;
316
+ }
317
+
318
+ function get_google_font_fields( $instance ) {
319
+ return array(
320
+ $instance['headline']['font'],
321
+ $instance['sub_headline']['font'],
322
+ );
323
+ }
324
+
325
+ /**
326
+ * Get the template variables for the headline
327
+ *
328
+ * @param $instance
329
+ * @param $args
330
+ *
331
+ * @return array
332
+ */
333
+ function get_template_variables( $instance, $args ) {
334
+ if( empty( $instance ) ) return array();
335
+
336
+ return array(
337
+ 'headline' => $instance['headline']['text'],
338
+ 'headline_destination_url' => $instance['headline']['destination_url'],
339
+ 'headline_new_window' => $instance['headline']['new_window'],
340
+ 'headline_tag' => $instance['headline']['tag'],
341
+ 'sub_headline' => $instance['sub_headline']['text'],
342
+ 'sub_headline_destination_url' => $instance['sub_headline']['destination_url'],
343
+ 'sub_headline_new_window' => $instance['sub_headline']['new_window'],
344
+ 'sub_headline_tag' => $instance['sub_headline']['tag'],
345
+ 'order' => $instance['order'],
346
+ 'has_divider' => ! empty( $instance['divider'] ) && $instance['divider']['style'] != 'none'
347
+ );
348
+ }
349
+
350
+ function wrapper_class_filter( $classes, $instance ){
351
+ if( $instance[ 'fittext' ] ) {
352
+ $classes[] = 'so-widget-fittext-wrapper';
353
+ wp_enqueue_script( 'sowb-fittext' );
354
+ }
355
+ return $classes;
356
+ }
357
+
358
+ function wrapper_data_filter( $data, $instance ) {
359
+ if( $instance['fittext'] ) {
360
+ $data['fit-text-compressor'] = $instance['fittext_compressor'];
361
+ }
362
+ return $data;
363
+ }
364
+
365
+ function modify_instance( $instance ) {
366
+ // Change the old divider weight into a divider thickness
367
+ if( isset( $instance['divider']['weight'] ) && ! isset( $instance['divider']['thickness'] ) ) {
368
+ switch( $instance['divider']['weight'] ) {
369
+ case 'medium':
370
+ $instance['divider']['thickness'] = 3;
371
+ break;
372
+ case 'thick':
373
+ $instance['divider']['thickness'] = 5;
374
+ break;
375
+ case 'thin' :
376
+ default :
377
+ $instance['divider']['thickness'] = 1;
378
+ break;
379
+ }
380
+ unset( $instance['divider']['weight'] );
381
+ }
382
+
383
+ // Change the old divider side margin into overall width
384
+ if( isset( $instance['divider']['side_margin'] ) && ! isset( $instance['divider']['width'] ) ) {
385
+ global $content_width;
386
+ $value = floatval( $instance['divider']['side_margin'] );
387
+
388
+ switch( $instance['divider']['side_margin_unit'] ) {
389
+ case 'px' :
390
+ $instance['divider']['width'] = ( ( !empty( $content_width ) ? $content_width : 960 ) - ( 2 * $value ) ) . 'px';
391
+ $instance['divider']['width_unit'] = 'px';
392
+ break;
393
+
394
+ case '%' :
395
+ $instance['divider']['width'] = ( 100 - (2 * $value) ) . '%';
396
+ $instance['divider']['width_unit'] = '%';
397
+ break;
398
+
399
+ default :
400
+ $instance['divider']['width'] = '80%';
401
+ $instance['divider']['width_unit'] = '%';
402
+ break;
403
+ }
404
+
405
+ unset( $instance['divider']['side_margin'] );
406
+ unset( $instance['divider']['side_margin_unit'] );
407
+ }
408
+
409
+ // Copy top margin over to bottom margin
410
+ if( isset( $instance['divider']['top_margin'] ) && ! isset( $instance['divider']['bottom_margin'] ) ) {
411
+ $instance['divider']['bottom_margin'] = $instance['divider']['top_margin'];
412
+ $instance['divider']['bottom_margin_unit'] = $instance['divider']['top_margin_unit'];
413
+ }
414
+
415
+ return $instance;
416
+ }
417
+ }
418
+
419
+ siteorigin_widget_register('sow-headline', __FILE__, 'SiteOrigin_Widget_Headline_Widget');
widgets/hero/hero.php CHANGED
@@ -430,7 +430,7 @@ class SiteOrigin_Widget_Hero_Widget extends SiteOrigin_Widget_Base_Slider {
430
  function wrapper_class_filter( $classes, $instance ){
431
  if( ! empty( $instance['design']['fittext'] ) ) {
432
  $classes[] = 'so-widget-fittext-wrapper';
433
- wp_enqueue_script( 'sow-fittext' );
434
  }
435
  return $classes;
436
  }
430
  function wrapper_class_filter( $classes, $instance ){
431
  if( ! empty( $instance['design']['fittext'] ) ) {
432
  $classes[] = 'so-widget-fittext-wrapper';
433
+ wp_enqueue_script( 'sowb-fittext' );
434
  }
435
  return $classes;
436
  }
widgets/image/image.php CHANGED
@@ -1,195 +1,195 @@
1
- <?php
2
- /*
3
- Widget Name: Image
4
- Description: A very simple image widget.
5
- Author: SiteOrigin
6
- Author URI: https://siteorigin.com
7
- */
8
-
9
- class SiteOrigin_Widget_Image_Widget extends SiteOrigin_Widget {
10
- function __construct() {
11
- parent::__construct(
12
- 'sow-image',
13
- __('SiteOrigin Image', 'so-widgets-bundle'),
14
- array(
15
- 'description' => __('A simple image widget with massive power.', 'so-widgets-bundle'),
16
- 'help' => 'https://siteorigin.com/widgets-bundle/image-widget-documentation/'
17
- ),
18
- array(
19
-
20
- ),
21
- false,
22
- plugin_dir_path(__FILE__)
23
- );
24
- }
25
-
26
- function get_widget_form() {
27
-
28
- return array(
29
- 'image' => array(
30
- 'type' => 'media',
31
- 'label' => __('Image file', 'so-widgets-bundle'),
32
- 'library' => 'image',
33
- 'fallback' => true,
34
- ),
35
-
36
- 'size' => array(
37
- 'type' => 'image-size',
38
- 'label' => __('Image size', 'so-widgets-bundle'),
39
- ),
40
-
41
- 'align' => array(
42
- 'type' => 'select',
43
- 'label' => __('Image alignment', 'so-widgets-bundle'),
44
- 'default' => 'default',
45
- 'options' => array(
46
- 'default' => __('Default', 'so-widgets-bundle'),
47
- 'left' => __('Left', 'so-widgets-bundle'),
48
- 'right' => __('Right', 'so-widgets-bundle'),
49
- 'center' => __('Center', 'so-widgets-bundle'),
50
- ),
51
- ),
52
-
53
- 'title' => array(
54
- 'type' => 'text',
55
- 'label' => __('Title text', 'so-widgets-bundle'),
56
- ),
57
-
58
- 'title_position' => array(
59
- 'type' => 'select',
60
- 'label' => __('Title position', 'so-widgets-bundle'),
61
- 'default' => 'hidden',
62
- 'options' => array(
63
- 'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
64
- 'above' => __( 'Above', 'so-widgets-bundle' ),
65
- 'below' => __( 'Below', 'so-widgets-bundle' ),
66
- ),
67
- ),
68
-
69
- 'alt' => array(
70
- 'type' => 'text',
71
- 'label' => __('Alt text', 'so-widgets-bundle'),
72
- ),
73
-
74
- 'url' => array(
75
- 'type' => 'link',
76
- 'label' => __('Destination URL', 'so-widgets-bundle'),
77
- ),
78
- 'new_window' => array(
79
- 'type' => 'checkbox',
80
- 'default' => false,
81
- 'label' => __('Open in new window', 'so-widgets-bundle'),
82
- ),
83
-
84
- 'bound' => array(
85
- 'type' => 'checkbox',
86
- 'default' => true,
87
- 'label' => __('Bound', 'so-widgets-bundle'),
88
- 'description' => __("Make sure the image doesn't extend beyond its container.", 'so-widgets-bundle'),
89
- ),
90
- 'full_width' => array(
91
- 'type' => 'checkbox',
92
- 'default' => false,
93
- 'label' => __('Full Width', 'so-widgets-bundle'),
94
- 'description' => __("Resize image to fit its container.", 'so-widgets-bundle'),
95
- ),
96
-
97
- );
98
- }
99
-
100
- function get_style_hash($instance) {
101
- return substr( md5( serialize( $this->get_less_variables( $instance ) ) ), 0, 12 );
102
- }
103
-
104
- public function get_template_variables( $instance, $args ) {
105
- // Workout the image title
106
- if ( ! empty( $instance['title'] ) ) {
107
- $title = $instance['title'];
108
- } else {
109
- // We do not want to use the default image titles as they're based on the file name without the extension
110
- $file_name = pathinfo( get_post_meta( $instance['image'], '_wp_attached_file', true ), PATHINFO_FILENAME );
111
- $title = get_the_title( $instance['image'] );
112
- if ( $title == $file_name ) {
113
- $title = '';
114
- }
115
- }
116
- $src = siteorigin_widgets_get_attachment_image_src(
117
- $instance['image'],
118
- $instance['size'],
119
- ! empty( $instance['image_fallback'] ) ? $instance['image_fallback'] : false
120
- );
121
-
122
- $attr = array();
123
- if( !empty($src) ) {
124
- $attr = array( 'src' => $src[0] );
125
-
126
- if ( ! empty( $src[1] ) ) {
127
- $attr['width'] = $src[1];
128
- }
129
-
130
- if ( ! empty( $src[2] ) ) {
131
- $attr['height'] = $src[2];
132
- }
133
-
134
- if ( function_exists( 'wp_get_attachment_image_srcset' ) ) {
135
- $attr['srcset'] = wp_get_attachment_image_srcset( $instance['image'], $instance['size'] );
136
- }
137
- // Don't add sizes attribute when Jetpack Photon is enabled, as it tends to have unexpected side effects.
138
- // This was to hotfix an issue. Can remove it when we find a way to make sure output of
139
- // `wp_get_attachment_image_sizes` is predictable with Photon enabled.
140
- if ( ! ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) ) ) {
141
- if ( function_exists( 'wp_get_attachment_image_sizes' ) ) {
142
- $attr['sizes'] = wp_get_attachment_image_sizes( $instance['image'], $instance['size'] );
143
- }
144
- }
145
- }
146
- $attr = apply_filters( 'siteorigin_widgets_image_attr', $attr, $instance, $this );
147
-
148
- $attr['title'] = $title;
149
-
150
- if ( ! empty( $instance['alt'] ) ) {
151
- $attr['alt'] = $instance['alt'];
152
- } else {
153
- $attr['alt'] = get_post_meta( $instance['image'], '_wp_attachment_image_alt', true );
154
- }
155
-
156
- $link_atts = array();
157
- if ( ! empty( $instance['new_window'] ) ) {
158
- $link_atts['target'] = '_blank';
159
- $link_atts['rel'] = 'noopener noreferrer';
160
- }
161
-
162
- return array(
163
- 'title' => $title,
164
- 'title_position' => $instance['title_position'],
165
- 'url' => $instance['url'],
166
- 'new_window' => $instance['new_window'],
167
- 'link_attributes' => $link_atts,
168
- 'attributes' => $attr,
169
- 'classes' => array( 'so-widget-image' ),
170
- );
171
- }
172
-
173
-
174
- function get_less_variables($instance){
175
- return array(
176
- 'image_alignment' => $instance['align'],
177
- 'image_display' => $instance['align'] == 'default' ? 'block' : 'inline-block',
178
- 'image_max_width' => ! empty( $instance['bound'] ) ? '100%' : '',
179
- 'image_height' => ! empty( $instance['bound'] ) ? 'auto' : '',
180
- 'image_width' => ! empty( $instance['full_width'] ) ? '100%' : ( ! empty( $instance['bound'] ) ? 'inherit' : '' ),
181
- );
182
- }
183
-
184
- function get_form_teaser(){
185
- if( class_exists( 'SiteOrigin_Premium' ) ) return false;
186
-
187
- return sprintf(
188
- __( 'Add a Lightbox to your images with %sSiteOrigin Premium%s', 'so-widgets-bundle' ),
189
- '<a href="https://siteorigin.com/downloads/premium/?featured_addon=plugin/lightbox" target="_blank" rel="noopener noreferrer">',
190
- '</a>'
191
- );
192
- }
193
- }
194
-
195
- siteorigin_widget_register('sow-image', __FILE__, 'SiteOrigin_Widget_Image_Widget');
1
+ <?php
2
+ /*
3
+ Widget Name: Image
4
+ Description: A very simple image widget.
5
+ Author: SiteOrigin
6
+ Author URI: https://siteorigin.com
7
+ */
8
+
9
+ class SiteOrigin_Widget_Image_Widget extends SiteOrigin_Widget {
10
+ function __construct() {
11
+ parent::__construct(
12
+ 'sow-image',
13
+ __('SiteOrigin Image', 'so-widgets-bundle'),
14
+ array(
15
+ 'description' => __('A simple image widget with massive power.', 'so-widgets-bundle'),
16
+ 'help' => 'https://siteorigin.com/widgets-bundle/image-widget-documentation/'
17
+ ),
18
+ array(
19
+
20
+ ),
21
+ false,
22
+ plugin_dir_path(__FILE__)
23
+ );
24
+ }
25
+
26
+ function get_widget_form() {
27
+
28
+ return array(
29
+ 'image' => array(
30
+ 'type' => 'media',
31
+ 'label' => __('Image file', 'so-widgets-bundle'),
32
+ 'library' => 'image',
33
+ 'fallback' => true,
34
+ ),
35
+
36
+ 'size' => array(
37
+ 'type' => 'image-size',
38
+ 'label' => __('Image size', 'so-widgets-bundle'),
39
+ ),
40
+
41
+ 'align' => array(
42
+ 'type' => 'select',
43
+ 'label' => __('Image alignment', 'so-widgets-bundle'),
44
+ 'default' => 'default',
45
+ 'options' => array(
46
+ 'default' => __('Default', 'so-widgets-bundle'),
47
+ 'left' => __('Left', 'so-widgets-bundle'),
48
+ 'right' => __('Right', 'so-widgets-bundle'),
49
+ 'center' => __('Center', 'so-widgets-bundle'),
50
+ ),
51
+ ),
52
+
53
+ 'title' => array(
54
+ 'type' => 'text',
55
+ 'label' => __('Title text', 'so-widgets-bundle'),
56
+ ),
57
+
58
+ 'title_position' => array(
59
+ 'type' => 'select',
60
+ 'label' => __('Title position', 'so-widgets-bundle'),
61
+ 'default' => 'hidden',
62
+ 'options' => array(
63
+ 'hidden' => __( 'Hidden', 'so-widgets-bundle' ),
64
+ 'above' => __( 'Above', 'so-widgets-bundle' ),
65
+ 'below' => __( 'Below', 'so-widgets-bundle' ),
66
+ ),
67
+ ),
68
+
69
+ 'alt' => array(
70
+ 'type' => 'text',
71
+ 'label' => __('Alt text', 'so-widgets-bundle'),
72
+ ),
73
+
74
+ 'url' => array(
75
+ 'type' => 'link',
76
+ 'label' => __('Destination URL', 'so-widgets-bundle'),
77
+ ),
78
+ 'new_window' => array(
79
+ 'type' => 'checkbox',
80
+ 'default' => false,
81
+ 'label' => __('Open in new window', 'so-widgets-bundle'),
82
+ ),
83
+
84
+ 'bound' => array(
85
+ 'type' => 'checkbox',
86
+ 'default' => true,
87
+ 'label' => __('Bound', 'so-widgets-bundle'),
88
+ 'description' => __("Make sure the image doesn't extend beyond its container.", 'so-widgets-bundle'),
89
+ ),
90
+ 'full_width' => array(
91
+ 'type' => 'checkbox',
92
+ 'default' => false,
93
+ 'label' => __('Full Width', 'so-widgets-bundle'),
94
+ 'description' => __("Resize image to fit its container.", 'so-widgets-bundle'),
95
+ ),
96
+
97
+ );
98
+ }
99
+
100
+ function get_style_hash($instance) {
101
+ return substr( md5( serialize( $this->get_less_variables( $instance ) ) ), 0, 12 );
102
+ }
103
+
104
+ public function get_template_variables( $instance, $args ) {
105
+ // Workout the image title
106
+ if ( ! empty( $instance['title'] ) ) {
107
+ $title = $instance['title'];
108
+ } else {
109
+ // We do not want to use the default image titles as they're based on the file name without the extension
110
+ $file_name = pathinfo( get_post_meta( $instance['image'], '_wp_attached_file', true ), PATHINFO_FILENAME );
111
+ $title = get_the_title( $instance['image'] );
112
+ if ( $title == $file_name ) {
113
+ $title = '';
114
+ }
115
+ }
116
+ $src = siteorigin_widgets_get_attachment_image_src(
117
+ $instance['image'],
118
+ $instance['size'],
119
+ ! empty( $instance['image_fallback'] ) ? $instance['image_fallback'] : false
120
+ );
121
+
122
+ $attr = array();
123
+ if( !empty($src) ) {
124
+ $attr = array( 'src' => $src[0] );
125
+
126
+ if ( ! empty( $src[1] ) ) {
127
+ $attr['width'] = $src[1];
128
+ }
129
+
130
+ if ( ! empty( $src[2] ) ) {
131
+ $attr['height'] = $src[2];
132
+ }
133
+
134
+ if ( function_exists( 'wp_get_attachment_image_srcset' ) ) {
135
+ $attr['srcset'] = wp_get_attachment_image_srcset( $instance['image'], $instance['size'] );
136
+ }
137
+ // Don't add sizes attribute when Jetpack Photon is enabled, as it tends to have unexpected side effects.
138
+ // This was to hotfix an issue. Can remove it when we find a way to make sure output of
139
+ // `wp_get_attachment_image_sizes` is predictable with Photon enabled.
140
+ if ( ! ( class_exists( 'Jetpack_Photon' ) && Jetpack::is_module_active( 'photon' ) ) ) {
141
+ if ( function_exists( 'wp_get_attachment_image_sizes' ) ) {
142
+ $attr['sizes'] = wp_get_attachment_image_sizes( $instance['image'], $instance['size'] );
143
+ }
144
+ }
145
+ }
146
+ $attr = apply_filters( 'siteorigin_widgets_image_attr', $attr, $instance, $this );
147
+
148
+ $attr['title'] = $title;
149
+
150
+ if ( ! empty( $instance['alt'] ) ) {
151
+ $attr['alt'] = $instance['alt'];
152
+ } else {
153
+ $attr['alt'] = get_post_meta( $instance['image'], '_wp_attachment_image_alt', true );
154
+ }
155
+
156
+ $link_atts = array();
157
+ if ( ! empty( $instance['new_window'] ) ) {
158
+ $link_atts['target'] = '_blank';
159
+ $link_atts['rel'] = 'noopener noreferrer';
160
+ }
161
+
162
+ return array(
163
+ 'title' => $title,
164
+ 'title_position' => $instance['title_position'],
165
+ 'url' => $instance['url'],
166
+ 'new_window' => $instance['new_window'],
167
+ 'link_attributes' => $link_atts,
168
+ 'attributes' => $attr,
169
+ 'classes' => array( 'so-widget-image' ),
170
+ );
171
+ }
172
+
173
+
174
+ function get_less_variables($instance){
175
+ return array(
176
+ 'image_alignment' => $instance['align'],
177
+ 'image_display' => $instance['align'] == 'default' ? 'block' : 'inline-block',
178
+ 'image_max_width' => ! empty( $instance['bound'] ) ? '100%' : '',
179
+ 'image_height' => ! empty( $instance['bound'] ) ? 'auto' : '',
180
+ 'image_width' => ! empty( $instance['full_width'] ) ? '100%' : ( ! empty( $instance['bound'] ) ? 'inherit' : '' ),
181
+ );
182
+ }
183
+
184
+ function get_form_teaser(){
185
+ if( class_exists( 'SiteOrigin_Premium' ) ) return false;
186
+
187
+ return sprintf(
188
+ __( 'Add a Lightbox to your images with %sSiteOrigin Premium%s', 'so-widgets-bundle' ),
189
+ '<a href="https://siteorigin.com/downloads/premium/?featured_addon=plugin/lightbox" target="_blank" rel="noopener noreferrer">',
190
+ '</a>'
191
+ );
192
+ }
193
+ }
194
+
195
+ siteorigin_widget_register('sow-image', __FILE__, 'SiteOrigin_Widget_Image_Widget');
widgets/tabs/tpl/default.php CHANGED
@@ -1,34 +1,36 @@
1
- <?php
2
- /**
3
- * @var array $args
4
- * @var array $instance
5
- * @var array $tabs
6
- * @var array $initial_tab_index
7
- */
8
-
9
- echo $args['before_title'] . $instance['title'] . $args['after_title'];
10
- ?>
11
- <div class="sow-tabs">
12
- <div class="sow-tabs-tab-container">
13
- <?php foreach ( $tabs as $i => $tab ) : ?>
14
- <div class="sow-tabs-tab<?php if ( $i == $initial_tab_index ) echo ' sow-tabs-tab-selected'; ?>"
15
- data-anchor="<?php echo sanitize_title_with_dashes( $tab['anchor'] ); ?>">
16
- <div class="sow-tabs-title">
17
- <?php echo $tab['before_title']; ?>
18
- <?php echo wp_kses_post( $tab['title'] ); ?>
19
- <?php echo $tab['after_title']; ?>
20
- </div>
21
- </div>
22
- <?php endforeach; ?>
23
- </div>
24
-
25
- <div class="sow-tabs-panel-container">
26
- <?php foreach ( $tabs as $i => $tab ) : ?>
27
- <div class="sow-tabs-panel">
28
- <div class="sow-tabs-panel-content">
29
- <?php $this->render_panel_content( $tab, $instance ); ?>
30
- </div>
31
- </div>
32
- <?php endforeach; ?>
33
- </div>
34
- </div>
 
 
1
+ <?php
2
+ /**
3
+ * @var array $args
4
+ * @var array $instance
5
+ * @var array $tabs
6
+ * @var array $initial_tab_index
7
+ */
8
+
9
+ if( ! empty( $instance['title'] ) ) {
10
+ echo $args['before_title'] . $instance['title'] . $args['after_title'];
11
+ }
12
+ ?>
13
+ <div class="sow-tabs">
14
+ <div class="sow-tabs-tab-container">
15
+ <?php foreach ( $tabs as $i => $tab ) : ?>
16
+ <div class="sow-tabs-tab<?php if ( $i == $initial_tab_index ) echo ' sow-tabs-tab-selected'; ?>"
17
+ data-anchor="<?php echo sanitize_title_with_dashes( $tab['anchor'] ); ?>">
18
+ <div class="sow-tabs-title">
19
+ <?php echo $tab['before_title']; ?>
20
+ <?php echo wp_kses_post( $tab['title'] ); ?>
21
+ <?php echo $tab['after_title']; ?>
22
+ </div>
23
+ </div>
24
+ <?php endforeach; ?>
25
+ </div>
26
+
27
+ <div class="sow-tabs-panel-container">
28
+ <?php foreach ( $tabs as $i => $tab ) : ?>
29
+ <div class="sow-tabs-panel">
30
+ <div class="sow-tabs-panel-content">
31
+ <?php $this->render_panel_content( $tab, $instance ); ?>
32
+ </div>
33
+ </div>
34
+ <?php endforeach; ?>
35
+ </div>
36
+ </div>