OoohBoi Steroids for Elementor - Version 1.7.4

Version Description

  • Added "silent" page refresh on window resize event to the Locomotive Scroll pages
  • Fixed Sucuri malware warning
  • Fixed laggy Locomotive Scroll Multiplier on Firefox
  • LOCOMOTION - all the built-in "fade" classes now work normally with Sections and Columns
Download this release

Release Info

Developer ooohboi
Plugin Icon 128x128 OoohBoi Steroids for Elementor
Version 1.7.4
Comparing to
See all releases

Code changes from version 1.7.3 to 1.7.4

assets/css/main.css CHANGED
@@ -309,132 +309,84 @@ body:not(.elementor-editor-active) .c-scrollbar {
309
  z-index: 99999;
310
  }
311
  /* FADe LEFT --------------- */
312
- body:not(.elementor-editor-active) .fade-left .elementor-container,
313
- body:not(.elementor-editor-active) .fade-left .elementor-background-overlay,
314
- body:not(.elementor-editor-active) .fade-left .elementor-widget-container {
315
  opacity: 0;
316
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
317
- transform: translateX(-30%);
318
  transition-delay: 0.35s;
 
319
  }
320
- body:not(.elementor-editor-active) .fade-left.is-inview .elementor-container,
321
- body:not(.elementor-editor-active) .fade-left.is-inview .elementor-background-overlay,
322
- body:not(.elementor-editor-active) .fade-left.is-inview .elementor-widget-container {
323
  opacity: 1;
324
- transform: translateX(0px);
325
  }
326
  /* -------------------------- */
327
  /* FADE RigHT --------------- */
328
- body:not(.elementor-editor-active) .fade-right .elementor-container,
329
- body:not(.elementor-editor-active) .fade-right .elementor-background-overlay,
330
- body:not(.elementor-editor-active) .fade-right .elementor-widget-container {
331
  opacity: 0;
332
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
333
- transform: translateX(30%);
334
  transition-delay: 0.35s;
 
335
  }
336
- body:not(.elementor-editor-active) .fade-right.is-inview .elementor-container,
337
- body:not(.elementor-editor-active) .fade-right.is-inview .elementor-background-overlay,
338
- body:not(.elementor-editor-active) .fade-right.is-inview .elementor-widget-container {
339
  opacity: 1;
340
- transform: translateX(0px);
341
  }
342
  /* -------------------------- */
343
  /* FADE UP --------------- */
344
- body:not(.elementor-editor-active) .fade-up .elementor-container,
345
- body:not(.elementor-editor-active) .fade-up .elementor-background-overlay,
346
- body:not(.elementor-editor-active) .fade-up .elementor-widget-container {
347
  opacity: 0;
348
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
349
- transform: translateY(10%);
350
  transition-delay: 0.35s;
 
351
  }
352
- body:not(.elementor-editor-active) .fade-up.is-inview .elementor-container,
353
- body:not(.elementor-editor-active) .fade-up.is-inview .elementor-background-overlay,
354
- body:not(.elementor-editor-active) .fade-up.is-inview .elementor-widget-container {
355
  opacity: 1;
356
- transform: translateY(0px);
357
  }
358
  /* -------------------------- */
359
  /* FADE DOWN --------------- */
360
- body:not(.elementor-editor-active) .fade-down .elementor-container,
361
- body:not(.elementor-editor-active) .fade-down .elementor-background-overlay,
362
- body:not(.elementor-editor-active) .fade-down .elementor-widget-container {
363
  opacity: 0;
364
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
365
- transform: translateY(-10%);
366
  transition-delay: 0.35s;
 
367
  }
368
- body:not(.elementor-editor-active) .fade-down.is-inview .elementor-container,
369
- body:not(.elementor-editor-active) .fade-down.is-inview .elementor-background-overlay,
370
- body:not(.elementor-editor-active) .fade-down.is-inview .elementor-widget-container {
371
  opacity: 1;
372
- transform: translateY(0px);
373
  }
374
  /* -------------------------- */
375
  /* FADE --------------- */
376
- body:not(.elementor-editor-active) .fade .elementor-container,
377
- body:not(.elementor-editor-active) .fade .elementor-background-overlay,
378
- body:not(.elementor-editor-active) .fade .elementor-widget-container {
379
- opacity: 0;
380
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
381
- transition-delay: 0.35s;
382
- }
383
- body:not(.elementor-editor-active) .fade.is-inview .elementor-container,
384
- body:not(.elementor-editor-active) .fade.is-inview .elementor-background-overlay,
385
- body:not(.elementor-editor-active) .fade.is-inview .elementor-widget-container {
386
- opacity: 1;
387
- }
388
- /* -------------------------- */
389
- /* REVeAL TOP --------------- OFFICIALLY UNSUPPORTED !!! */
390
- body:not(.elementor-editor-active) .reveal-top .elementor-widget-container {
391
- height: 0;
392
- overflow: hidden;
393
- transition: all 1.52s cubic-bezier(.215, .61, .355, 1);
394
- transition-delay: 0.35s;
395
- }
396
- body:not(.elementor-editor-active) .reveal-top.is-inview .elementor-widget-container {
397
- height: 100%;
398
- }
399
- body:not(.elementor-editor-active) .reveal-top .elementor-widget-container img {
400
- height: 40vh;
401
- display: block;
402
- margin: 0 auto;
403
- object-fit: cover;
404
- }
405
- /* -------------------------- */
406
- /* REVeAL LEFT --------------- */
407
- body:not(.elementor-editor-active) .reveal-left .elementor-widget-container {
408
- width: 0;
409
- height: 100%;
410
- transition: all 1.52s cubic-bezier(.215, .61, .355, 1);
411
- transition-delay: 0.35s;
412
- }
413
- body:not(.elementor-editor-active) .reveal-left.is-inview .elementor-widget-container {
414
- width: 100%;
415
- }
416
- body:not(.elementor-editor-active) .reveal-left .elementor-widget-container img {
417
- height: 40vh;
418
- display: block;
419
- margin: 0 auto;
420
- object-fit: cover;
421
- }
422
- /* -------------------------- */
423
- /* ZOOM IN --------------- */
424
- body:not(.elementor-editor-active) .zoom-in .elementor-widget-container {
425
  opacity: 0;
426
- transform: scale(1.2);
427
- transition: all 1s cubic-bezier(.215, .61, .355, 1);
428
  transition-delay: 0.35s;
429
  }
430
- body:not(.elementor-editor-active) .zoom-in.is-inview .elementor-widget-container {
 
 
431
  opacity: 1;
432
- transform: scale(1)
433
- }
434
- body:not(.elementor-editor-active) .zoom-in .elementor-widget-container img {
435
- height: 40vh;
436
- display: block;
437
- margin: 0 auto;
438
- object-fit: cover;
439
  }
440
  /* -------------------------- */
309
  z-index: 99999;
310
  }
311
  /* FADe LEFT --------------- */
312
+ body:not(.elementor-editor-active) .elementor-section.effect-fade-left,
313
+ body:not(.elementor-editor-active) .elementor-column.effect-fade-left,
314
+ body:not(.elementor-editor-active) [data-element_type="widget"].effect-fade-left .elementor-widget-container {
315
  opacity: 0;
316
+ transition: left 1s cubic-bezier(.215, .61, .355, 1), opacity 1s cubic-bezier(.215, .61, .355, 1);
317
+ left: -30%;
318
  transition-delay: 0.35s;
319
+ position: relative;
320
  }
321
+ body:not(.elementor-editor-active) .fade-left.elementor-section.effect-fade-left,
322
+ body:not(.elementor-editor-active) .fade-left.elementor-column.effect-fade-left,
323
+ body:not(.elementor-editor-active) [data-element_type="widget"].fade-left.effect-fade-left .elementor-widget-container {
324
  opacity: 1;
325
+ left: 0px;
326
  }
327
  /* -------------------------- */
328
  /* FADE RigHT --------------- */
329
+ body:not(.elementor-editor-active) .elementor-section.effect-fade-right,
330
+ body:not(.elementor-editor-active) .elementor-column.effect-fade-right,
331
+ body:not(.elementor-editor-active) [data-element_type="widget"].effect-fade-right .elementor-widget-container {
332
  opacity: 0;
333
+ transition: left 1s cubic-bezier(.215, .61, .355, 1), opacity 1s cubic-bezier(.215, .61, .355, 1);
334
+ left: 30%;
335
  transition-delay: 0.35s;
336
+ position: relative;
337
  }
338
+ body:not(.elementor-editor-active) .fade-right.elementor-section.effect-fade-right,
339
+ body:not(.elementor-editor-active) .fade-right.elementor-column.effect-fade-right,
340
+ body:not(.elementor-editor-active) [data-element_type="widget"].fade-right.effect-fade-right .elementor-widget-container {
341
  opacity: 1;
342
+ left: 0px;
343
  }
344
  /* -------------------------- */
345
  /* FADE UP --------------- */
346
+ body:not(.elementor-editor-active) .elementor-section.effect-fade-up,
347
+ body:not(.elementor-editor-active) .elementor-column.effect-fade-up,
348
+ body:not(.elementor-editor-active) [data-element_type="widget"].effect-fade-up .elementor-widget-container {
349
  opacity: 0;
350
+ transition: top 1s cubic-bezier(.215, .61, .355, 1), opacity 1s cubic-bezier(.215, .61, .355, 1);
351
+ top: -10%;
352
  transition-delay: 0.35s;
353
+ position: relative;
354
  }
355
+ body:not(.elementor-editor-active) .fade-up.elementor-section.effect-fade-up,
356
+ body:not(.elementor-editor-active) .fade-up.elementor-column.effect-fade-up,
357
+ body:not(.elementor-editor-active) [data-element_type="widget"].fade-up.effect-fade-up .elementor-widget-container {
358
  opacity: 1;
359
+ top: 0px;
360
  }
361
  /* -------------------------- */
362
  /* FADE DOWN --------------- */
363
+ body:not(.elementor-editor-active) .elementor-section.effect-fade-down,
364
+ body:not(.elementor-editor-active) .elementor-column.effect-fade-down,
365
+ body:not(.elementor-editor-active) [data-element_type="widget"].effect-fade-down .elementor-widget-container {
366
  opacity: 0;
367
+ transition: top 1s cubic-bezier(.215, .61, .355, 1), opacity 1s cubic-bezier(.215, .61, .355, 1);
368
+ top: 10%;
369
  transition-delay: 0.35s;
370
+ position: relative;
371
  }
372
+ body:not(.elementor-editor-active) .fade-down.elementor-section.effect-fade-down,
373
+ body:not(.elementor-editor-active) .fade-down.elementor-column.effect-fade-down,
374
+ body:not(.elementor-editor-active) [data-element_type="widget"].fade-down.effect-fade-down .elementor-widget-container {
375
  opacity: 1;
376
+ top: 0;
377
  }
378
  /* -------------------------- */
379
  /* FADE --------------- */
380
+ body:not(.elementor-editor-active) .elementor-section.effect-fade-in,
381
+ body:not(.elementor-editor-active) .elementor-column.effect-fade-in,
382
+ body:not(.elementor-editor-active) [data-element_type="widget"].effect-fade-in .elementor-widget-container {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  opacity: 0;
384
+ transition: opacity 1s cubic-bezier(.215, .61, .355, 1);
 
385
  transition-delay: 0.35s;
386
  }
387
+ body:not(.elementor-editor-active) .fade-in.elementor-section.effect-fade-in,
388
+ body:not(.elementor-editor-active) .fade-in.elementor-column.effect-fade-in,
389
+ body:not(.elementor-editor-active) [data-element_type="widget"].fade-in.effect-fade-in .elementor-widget-container {
390
  opacity: 1;
 
 
 
 
 
 
 
391
  }
392
  /* -------------------------- */
assets/js/ooohboi-libs-locomotion.js CHANGED
@@ -7,6 +7,10 @@
7
  var loco_scroll_tablet = parseInt( device_settings.allow_tablet );
8
  var loco_scroll_mobile = parseInt( device_settings.allow_mobile );
9
  var loco_allow_refresh = parseInt( device_settings.allow_refresh );
 
 
 
 
10
 
11
  $window.on( 'elementor/frontend/init', function() {
12
  // reference to THIS / Elementor
@@ -52,7 +56,6 @@
52
  multiplier: loco_multiplier,
53
  tablet: { smooth: loco_scroll_tablet },
54
  smartphone: { smooth: loco_scroll_mobile },
55
- reloadOnContextChange: true,
56
  } );
57
  };
58
  } );
@@ -61,8 +64,8 @@
61
  $window.load( function( $ ) {
62
  var loco_scroll_loaded = setInterval( function() {
63
  if( w.sfe_loco_scroll && Object.keys( w.sfe_loco_scroll ).length !== 0 ) {
64
- // height fix deprecated in favour of resize listener
65
- if( ! loco_allow_refresh ) w.dispatchEvent( new Event( 'resize' ) );
66
  // anchor/hash
67
  var all_data_scroll_to = document.querySelectorAll( '[data-jump-to]' ), i;
68
  for( i = 0; i < all_data_scroll_to.length; ++ i ) {
@@ -80,22 +83,20 @@
80
  } );
81
  }
82
  // get off the duty
 
83
  clearInterval( loco_scroll_loaded );
84
  }
85
  }, 100 );
86
  } );
87
  // handle resize --- we have to refresh the page upon resize!
88
- w.addEventListener( 'resize', debouncer( e => {
89
- if( w.sfe_loco_scroll && Object.keys( w.sfe_loco_scroll ).length !== 0 && loco_allow_refresh ) {
90
- w.location.reload();
 
 
 
 
 
91
  }
92
- }, true ) );
93
- function debouncer( f ) {
94
- var debounce_timer;
95
- return function( e ) {
96
- if( debounce_timer ) clearTimeout( debounce_timer );
97
- debounce_timer = setTimeout( f, 500, e );
98
- };
99
- }
100
-
101
  }( jQuery, window, window.sfe_loco_scroll = window.sfe_loco_scroll || {} ) );
7
  var loco_scroll_tablet = parseInt( device_settings.allow_tablet );
8
  var loco_scroll_mobile = parseInt( device_settings.allow_mobile );
9
  var loco_allow_refresh = parseInt( device_settings.allow_refresh );
10
+ var resize_timer;
11
+
12
+ // fix the Firefox scroll lag
13
+ if( navigator.userAgent.indexOf( "Firefox" ) !== -1 ) loco_multiplier *= 3;
14
 
15
  $window.on( 'elementor/frontend/init', function() {
16
  // reference to THIS / Elementor
56
  multiplier: loco_multiplier,
57
  tablet: { smooth: loco_scroll_tablet },
58
  smartphone: { smooth: loco_scroll_mobile },
 
59
  } );
60
  };
61
  } );
64
  $window.load( function( $ ) {
65
  var loco_scroll_loaded = setInterval( function() {
66
  if( w.sfe_loco_scroll && Object.keys( w.sfe_loco_scroll ).length !== 0 ) {
67
+ // fix the miscalculated page height
68
+ if( ! loco_allow_refresh ) w.dispatchEvent( new Event( 'resize' ) );
69
  // anchor/hash
70
  var all_data_scroll_to = document.querySelectorAll( '[data-jump-to]' ), i;
71
  for( i = 0; i < all_data_scroll_to.length; ++ i ) {
83
  } );
84
  }
85
  // get off the duty
86
+ refresh_loc();
87
  clearInterval( loco_scroll_loaded );
88
  }
89
  }, 100 );
90
  } );
91
  // handle resize --- we have to refresh the page upon resize!
92
+ window.onresize = () => {
93
+ clearTimeout( resize_timer );
94
+ resize_timer = setTimeout( refresh_loc, 500 );
95
+ };
96
+ function refresh_loc() {
97
+ if( w.sfe_loco_scroll && Object.keys( w.sfe_loco_scroll ).length !== 0 && loco_allow_refresh ) {
98
+ w.sfe_loco_scroll.update();
99
+ w.sfe_loco_scroll.scroll.reinitScrollBar();
100
  }
101
+ }
 
 
 
 
 
 
 
 
102
  }( jQuery, window, window.sfe_loco_scroll = window.sfe_loco_scroll || {} ) );
inc/RationalOptionPages.php DELETED
@@ -1,866 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * RationalOptionPages class
5
- *
6
- * @category WordPress Development
7
- * @package RationalOptionPages
8
- * @author Jeremy Hixon <jeremy@jeremyhixon.com>
9
- * @copyright Copyright (c) 2016
10
- * @link http://jeremyhixon.com
11
- * @version 1.0.0
12
- * phpcs:ignoreFile -- this is not a core file
13
- */
14
- class RationalOptionPages {
15
- /* ==========================================================================
16
- Vars
17
- ========================================================================== */
18
- protected $attributes = array(
19
- 'input' => array(
20
- 'autocomplete' => false,
21
- 'autofocus' => false,
22
- 'disabled' => false,
23
- 'list' => false,
24
- 'max' => false,
25
- 'maxlength' => false,
26
- 'min' => false,
27
- 'pattern' => false,
28
- 'readonly' => false,
29
- 'required' => false,
30
- 'size' => false,
31
- 'step' => false,
32
- ),
33
- 'select' => array(
34
- 'multiple' => false,
35
- 'size' => 4,
36
- ),
37
- 'textarea' => array(
38
- 'cols' => 20,
39
- 'rows' => 2,
40
- 'wrap' => 'soft',
41
- ),
42
- );
43
- protected $defaults = array(
44
- 'add_menu_page' => array(
45
- 'page_title' => 'Option Page',
46
- 'menu_title' => 'Option Page',
47
- 'capability' => 'manage_options',
48
- 'menu_slug' => 'option_page',
49
- 'callback' => false,
50
- 'icon_url' => false,
51
- 'position' => null,
52
- ),
53
- 'add_settings_field' => array(
54
- 'id' => 'settings_field',
55
- 'title' => 'Settings Field',
56
- 'callback' => false,
57
- 'page' => 'option_page',
58
- 'section' => 'settings_section',
59
- 'args' => false,
60
- ),
61
- 'add_settings_section' => array(
62
- 'id' => 'settings_section',
63
- 'title' => 'Settings Section',
64
- 'callback' => false,
65
- 'page' => 'option_page',
66
- ),
67
- 'add_submenu_page' => array(
68
- 'parent_slug' => 'option_page',
69
- 'page_title' => 'Sub Option Page',
70
- 'menu_title' => 'Sub Option Page',
71
- 'capability' => 'manage_options',
72
- 'menu_slug' => 'sub_option_page',
73
- 'callback' => false,
74
- ),
75
- );
76
- protected $errors;
77
- protected $fields = array(
78
- 'checkbox' => array(
79
- 'checked' => false,
80
- 'value' => 'on',
81
- ),
82
- 'text' => array(
83
- 'class' => 'regular-text',
84
- 'placeholder' => '',
85
- 'value' => false,
86
- ),
87
- 'textarea' => array(
88
- 'class' => 'large-text',
89
- 'placeholder' => '',
90
- 'rows' => 10,
91
- 'value' => false,
92
- ),
93
- 'wp_editor' => array(
94
- 'wpautop' => true,
95
- 'media_buttons' => true,
96
- 'textarea_rows' => 'default',
97
- 'tabindex' => false,
98
- 'editor_css' => false,
99
- 'editor_class' => '',
100
- 'editor_height' => false,
101
- 'teeny' => false,
102
- 'dfw' => false,
103
- 'tinymce' => true,
104
- 'quicktags' => true,
105
- 'drag_drop_upload' => false,
106
- ),
107
- );
108
- protected $media_script = false;
109
- protected $notices;
110
- protected $options;
111
- protected $pages = array();
112
- protected $subpages = array();
113
- protected $points;
114
-
115
- /* ==========================================================================
116
- Magic methods
117
- ========================================================================== */
118
- /**
119
- * Catches unknown method calls
120
- *
121
- * @param string $method The method being requested
122
- * @param array $arguments Array of arguments passed to the method
123
- */
124
- public function __call( $method, $arguments ) {
125
- $request = explode( '|', $method );
126
- $source = $request[0];
127
- $page_key = !empty( $request[1] ) ? $request[1] : false;
128
- $section_key = !empty( $request[2] ) ? $request[2] : false;
129
- $field_key = !empty( $request[3] ) ? $request[3] : false;
130
-
131
- switch ( $source ) {
132
- case 'add_menu_page':
133
- case 'add_submenu_page':
134
- $this->build_menu_page( $page_key );
135
- break;
136
- case 'add_settings_section':
137
- $this->build_settings_section( $page_key, $section_key );
138
- break;
139
- case 'add_settings_field':
140
- $this->build_settings_field( $page_key, $section_key, $field_key );
141
- break;
142
- case 'register_setting':
143
- $input = $this->sanitize_setting( $page_key, $arguments[0] );
144
- return $input;
145
- break;
146
- default:
147
- $this->submit_notice( $method );
148
- }
149
- }
150
-
151
- /**
152
- * Class construct method. Configures class and hooks into WordPress.
153
- *
154
- * @param array $pages Array of option pages
155
- */
156
- public function __construct( $pages = array() ) {
157
- foreach ( $pages as $page_key => $page_params ) {
158
- $this->pages[ $page_key ] = $this->validate_page( $page_key, $page_params );
159
- }
160
- $this->pages = array_merge( $this->pages, $this->subpages );
161
-
162
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
163
- add_action( 'admin_head', array( $this, 'admin_head' ) );
164
- add_action( 'admin_init', array( $this, 'admin_init' ) );
165
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
166
- add_action( 'admin_notices', array( $this, 'admin_notices' ) );
167
- }
168
-
169
- /* ==========================================================================
170
- WordPress hooks
171
- ========================================================================== */
172
- /**
173
- * Action: admin_enqueue_scripts
174
- * Conditionally queue's up jQuery and the media uploader script
175
- */
176
- public function admin_enqueue_scripts() {
177
- if ( $this->media_script ) {
178
- wp_enqueue_script( 'jquery' );
179
- wp_enqueue_media();
180
- }
181
- }
182
-
183
- /**
184
- * Action: admin_head
185
- * Conditionally adds the script to manage media uploads
186
- */
187
- public function admin_head() {
188
- if ( $this->media_script ) {
189
- ?> <script>
190
- jQuery.noConflict();
191
- (function($) {
192
- $(function() {
193
- var mediaUploader,
194
- rationalMediaButton = $( '.rational-media-upload' ),
195
- rationalMediaAttachment;
196
-
197
- rationalMediaButton.click( function( e ) {
198
- e.preventDefault();
199
- var rationalMediaDestination = $( this ).prev( 'input' );
200
-
201
- if ( mediaUploader ) {
202
- mediaUploader.open();
203
- return;
204
- }
205
-
206
- mediaUploader = wp.media.frames.file_frame = wp.media( {
207
- title: 'Choose File',
208
- button: {
209
- text: 'Choose File',
210
- },
211
- multiple: false,
212
- } );
213
-
214
- mediaUploader.on( 'select', function() {
215
- rationalMediaAttachment = mediaUploader.state().get('selection').first().toJSON();
216
- rationalMediaDestination.val( rationalMediaAttachment.url );
217
- } );
218
-
219
- mediaUploader.open();
220
- } );
221
- });
222
- })(jQuery);
223
- </script>
224
- <?php }
225
- }
226
-
227
- /**
228
- * Action: admin_init
229
- * Registers settings, adds sections and fields
230
- */
231
- public function admin_init() {
232
- foreach ( $this->pages as $page_key => $page_params ) {
233
- // Finalize sanitize
234
- if ( empty( $page_params['custom'] ) && !is_array( $page_params['sanitize'] ) ) {
235
- $page_params['sanitize'] = array( $this, $page_params['sanitize'] );
236
- }
237
-
238
- register_setting(
239
- $page_key,
240
- $page_key,
241
- $page_params['sanitize']
242
- );
243
-
244
- if ( !empty( $page_params['sections'] ) ) {
245
- foreach ( $page_params['sections'] as $section_key => $section_params ) {
246
- // Sort and trim the array for the function
247
- $sort_order = array_keys( $this->defaults['add_settings_section'] );
248
- $params = $this->sort_array( $section_params, $sort_order );
249
- $params = array_slice( $params, 0, count( $this->defaults['add_settings_section'] ) );
250
-
251
- // Finalize callback
252
- if ( empty( $params['custom'] ) && !is_array( $params['callback'] ) ) {
253
- $params['callback'] = array( $this, $params['callback'] );
254
- }
255
-
256
- add_settings_section( ...array_values( $params ) );
257
-
258
- if ( !empty( $section_params['fields'] ) ) {
259
- foreach ( $section_params['fields'] as $field_key => $field_params ) {
260
- // Check for "media" type for adding script
261
- if ( !$this->media_script && $field_params['type'] === 'media' ) {
262
- $this->media_script = true;
263
- }
264
-
265
- // Sort and trim the array for the function
266
- $sort_order = array_keys( $this->defaults['add_settings_field'] );
267
- $params = $this->sort_array( $field_params, $sort_order );
268
- $params = array_slice( $params, 0, count( $this->defaults['add_settings_field'] ) );
269
-
270
- // Add label wrapper on title
271
- if (
272
- !in_array( $field_params['type'], array( 'radio' ) ) &&
273
- ( empty( $field_params['no_label'] ) || $field_params['no_label'] === false )
274
- ) {
275
- $params['title'] = "<label for='{$params['id']}'>{$params['title']}</label>";
276
- }
277
-
278
- // Finalize callback
279
- if ( empty( $params['custom'] ) && !is_array( $params['callback'] ) ) {
280
- $params['callback'] = array( $this, $params['callback'] );
281
- }
282
-
283
- add_settings_field( ...array_values( $params ) );
284
- }
285
- }
286
- }
287
- }
288
- }
289
- }
290
-
291
- /**
292
- * Action: admin_menu. Adding the option pages to the admin menu.
293
- */
294
- public function admin_menu() {
295
- $all_pages = array_merge( $this->pages, $this->subpages );
296
-
297
- foreach ( $all_pages as $page ) {
298
- // Sort and trim the array for the function
299
- $sort_order = array_keys( $this->defaults[ $page['function'] ] );
300
- $params = $this->sort_array( $page, $sort_order );
301
- $params = array_slice( $params, 0, count( $this->defaults[ $page['function'] ] ) );
302
-
303
- // Finalize callback
304
- $params['callback'] = array( $this, $params['callback'] );
305
-
306
- call_user_func_array( $page['function'], array_values( $params ) );
307
- }
308
- }
309
-
310
- /**
311
- * Action: admin_notices. Spitting out notices when needed.
312
- */
313
- public function admin_notices() {
314
- // notice-error, notice-warning, notice-success, or notice-info.
315
- if ( !empty( $this->errors ) ) {
316
- foreach ( $this->errors as $error ) {
317
- echo $error;
318
- }
319
- }
320
- if ( !empty( $this->notices ) ) {
321
- foreach ( $this->notices as $notice ) {
322
- echo $notice;
323
- }
324
- }
325
-
326
- // update point in array for future reference
327
- $this->points['admin_notices'] = true;
328
- }
329
-
330
- /* ==========================================================================
331
- Helpers
332
- ========================================================================== */
333
- public function add_page( $page_key, $page_params ) {
334
- $this->pages[ $page_key ] = $this->validate_page( $page_key, $page_params );
335
- }
336
-
337
- /**
338
- * Builds the menu page
339
- *
340
- * @param string $page_key The array key of the page needing built
341
- */
342
- protected function build_menu_page( $page_key ) {
343
- $page = $this->pages[ $page_key ];
344
- $this->options = get_option( $page_key, array() );
345
- ?><div class="wrap ob-settings-page">
346
- <h1><?php echo $GLOBALS['title']; ?></h1><?php
347
-
348
- if ( !empty( $page['sections'] ) ) {
349
- ?><form action="options.php" method="post"><?php
350
- settings_errors( $page_key );
351
- settings_fields( $page_key );
352
- do_settings_sections( $page['menu_slug'] );
353
- if ( $this->has_fields( $page ) ) {
354
- submit_button();
355
- }
356
- ?></form><?php
357
- }
358
- ?></div><?php
359
- }
360
-
361
- /**
362
- * Builds the fields themselves
363
- *
364
- * @param string $page_key The array key of the page
365
- * @param string $section_key The array key of the section
366
- * @param string $field_key The array key of the field
367
- */
368
- protected function build_settings_field( $page_key, $section_key, $field_key ) {
369
- $page = $this->pages[ $page_key ];
370
- $section = $page['sections'][ $section_key ];
371
- $field = $section['fields'][ $field_key ];
372
-
373
- if ( $field['type'] !== 'checkbox' ) {
374
- $field['value'] = !empty( $this->options[ $field['id'] ] ) ? $this->options[ $field['id'] ] : $field['value'];
375
- }
376
-
377
- // Additional attributes
378
- if ( !empty( $field['attributes'] ) ) {
379
- $attributes = array();
380
- foreach ( $field['attributes'] as $attribute => $value ) {
381
- if ( !empty( $value ) ) {
382
- $attributes[] = "{$attribute}='{$value}'";
383
- }
384
- }
385
- }
386
-
387
- // Sanitize field values, unless 'sanitize' was set to false for this field.
388
- if ( !isset( $field['sanitize'] ) || $field['sanitize']) {
389
- $field['value'] = strip_tags($field['value']); // Removes HTML tags
390
- $field['value'] = esc_attr($field['value']); // Escapes field for HTML attributes
391
- }
392
-
393
- switch ( $field['type'] ) {
394
- case 'checkbox':
395
- $checked = $field['checked'] ? 'checked' : '';
396
- if ( isset( $this->options[ $field['id'] ] ) ) {
397
- $checked = checked( $field['value'], $this->options[ $field['id'] ], false );
398
- }
399
- printf(
400
- '<label><input %s %s id="%s" name="%s" title="%s" type="checkbox" value="%s">&nbsp; %s</label>',
401
- $checked, // checked
402
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
403
- $field['id'], // id
404
- "{$page_key}[{$field['id']}]", // name
405
- $field['title_attr'], // title
406
- $field['value'], // value
407
- !empty( $field['text'] ) ? $field['text'] : '' // text
408
- );
409
- break;
410
- case 'media':
411
- $upload_button = sprintf(
412
- '<input class="button rational-media-upload" type="button" value="Upload">'
413
- );
414
- printf(
415
- '<input %s id="%s" name="%s" %s title="%s" type="text" value="%s" %s>%s%s',
416
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
417
- $field['id'], // id
418
- "{$page_key}[{$field['id']}]", // name
419
- !empty( $field['placeholder'] ) ? "placeholder='{$field['placeholder']}'" : '', // placeholder
420
- $field['title_attr'], // title
421
- $field['value'], // value
422
- !empty( $attributes ) ? implode( ' ', $attributes ) : '', // additional attributes
423
- $upload_button, // upload button
424
- !empty( $field['text'] ) ? "<p class='help'>{$field['text']}</p>" : '' // text
425
- );
426
- break;
427
- case 'radio':
428
- echo '<fieldset><legend class="screen-reader-text">' . $field['title'] . '</legend>';
429
- $c = 0;
430
- foreach ( $field['choices'] as $value => $label ) {
431
- $checked = $value === $field['value'] ? 'checked' : '';
432
- if ( isset( $this->options[ $field['id'] ] ) ) {
433
- $checked = $value === $this->options[ $field['id'] ] ? 'checked' : '';
434
- }
435
- printf(
436
- '<label><input %s %s id="%s" name="%s" type="radio" title="%s" value="%s">&nbsp; %s</label>%s',
437
- $checked, // checked
438
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
439
- $field['id'], // id
440
- "{$page_key}[{$field['id']}]", // name
441
- $label, // title
442
- $value, // value
443
- $label, // label
444
- $c < count( $field['choices'] ) - 1 ? '<br>' : '' // line-break
445
- );
446
- $c++;
447
- }
448
- echo '</fieldset>';
449
- break;
450
- case 'select':
451
- if (!empty($field['attributes']) && isset($field['attributes']['multiple']) && $field['attributes']['multiple']) {
452
- $field_tag_name = "{$page_key}[{$field['id']}][]";
453
- $field_name = "{$field['id']}[]";
454
- }
455
- else {
456
- $field_tag_name = "{$page_key}[{$field['id']}]";
457
- $field_name = "{$field['id']}";
458
- }
459
- printf(
460
- '<select %s %s id="%s" name="%s" title="%s">',
461
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
462
- !empty( $attributes ) ? implode(' ', $attributes) : '',
463
- $field['id'], // id
464
- $field_tag_name, // name
465
- $field['title_attr'] // title
466
- );
467
- foreach ( $field['choices'] as $value => $text ) {
468
- $selected = $value === $field['value'] ? 'selected' : '';
469
- if ( isset( $this->options[ $field['id'] ] ) ) {
470
- if (!is_array($this->options[ $field['id'] ] ) ) {
471
- $selected = $value === $this->options[ $field['id'] ] ? 'selected="selected"' : '';
472
- }
473
- else {
474
- $selected = '';
475
- foreach ($this->options[ $field['id'] ] as $option) {
476
- if ($value === $option) {
477
- $selected = 'selected="selected"';
478
- continue;
479
- }
480
- }
481
- }
482
- }
483
- printf(
484
- '<option %s value="%s">%s</option>',
485
- $selected, // selected
486
- $value, // value
487
- $text // text
488
- );
489
- }
490
- echo '</select>';
491
- break;
492
- case 'textarea':
493
- printf(
494
- '<textarea %s id="%s" name="%s" %s %s title="%s">%s</textarea>%s',
495
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
496
- $field['id'], // id
497
- "{$page_key}[{$field['id']}]", // name
498
- !empty( $field['placeholder'] ) ? "placeholder='{$field['placeholder']}'" : '', // placeholder
499
- !empty( $field['rows'] ) ? "rows='{$field['rows']}'" : '', // rows
500
- $field['title_attr'], // title
501
- $field['value'], // value
502
- !empty( $field['text'] ) ? "<p class='help'>{$field['text']}</p>" : '' // text
503
- );
504
- break;
505
- case 'wp_editor':
506
- $field['textarea_name'] = "{$page_key}[{$field['id']}]";
507
- wp_editor( $field['value'], $field['id'], array(
508
- 'textarea_name' => $field['textarea_name'],
509
- ) );
510
- echo !empty( $field['text'] ) ? "<p class='help'>{$field['text']}</p>" : '';
511
- break;
512
- default:
513
- printf(
514
- '<input %s id="%s" name="%s" %s title="%s" type="%s" value="%s" %s>%s',
515
- !empty( $field['class'] ) ? "class='{$field['class']}'" : '', // class
516
- $field['id'], // id
517
- "{$page_key}[{$field['id']}]", // name
518
- !empty( $field['placeholder'] ) ? "placeholder='{$field['placeholder']}'" : '', // placeholder
519
- $field['title_attr'], // title
520
- $field['type'], // type
521
- $field['value'], // value
522
- !empty( $attributes ) ? implode( ' ', $attributes ) : '', // additional attributes
523
- !empty( $field['text'] ) ? "<p class='help'>{$field['text']}</p>" : '' // text
524
- );
525
- }
526
- }
527
-
528
- /**
529
- * Builds the settings sections
530
- *
531
- * @param string $page_key The array key of the page
532
- * @param type $section_key The array key of the section
533
- */
534
- protected function build_settings_section( $page_key, $section_key ) {
535
- $page = $this->pages[ $page_key ];
536
- $section = $page['sections'][ $section_key ];
537
-
538
- echo !empty( $section['text'] ) ? $section['text'] : '';
539
-
540
- if ( !empty( $section['include'] ) ) {
541
- include $section['include'];
542
- }
543
- }
544
-
545
- /**
546
- * Determines if the option page has fields or not
547
- *
548
- * @param array $page The page array
549
- *
550
- * @return boolean True if fields are found, false otherwise
551
- */
552
- protected function has_fields( $page ) {
553
- if ( !empty( $page['sections'] ) ) {
554
- foreach ( $page['sections'] as $section ) {
555
- if ( !empty( $section['fields'] ) ) {
556
- return true;
557
- }
558
- }
559
- }
560
- return false;
561
- }
562
-
563
- /**
564
- * Cleans up the option page submissions before submitting to the DB
565
- *
566
- * @param string $page_key The array key of the page
567
- *
568
- * @return array The sanitized post input
569
- */
570
- protected function sanitize_setting( $page_key, $input ) {
571
- $page = $this->pages[ $page_key ];
572
-
573
- if ( !empty( $page['sections'] ) ) {
574
- foreach ( $page['sections'] as $section ) {
575
- if ( !empty( $section['fields'] ) ) {
576
- foreach ( $section['fields'] as $field ) {
577
- switch ( $field['type'] ) {
578
- case 'checkbox':
579
- if ( empty( $input[ $field['id'] ] ) ) {
580
- $input[ $field['id'] ] = false;
581
- }
582
- break;
583
- default:
584
- // Sanitize by default; skip if this field's 'sanitize' setting is false.
585
- if ( !isset($field['sanitize']) || $field['sanitize'] ) {
586
- $input[ $field['id'] ] = strip_tags($input[ $field['id'] ]);
587
- $input[ $field['id'] ] = esc_attr($input[ $field['id'] ]);
588
- }
589
- }
590
- }
591
- }
592
- }
593
- }
594
-
595
- return $input;
596
- }
597
-
598
- /**
599
- * Converts human-readable strings into more machine-friendly formats
600
- *
601
- * @param string $text String to be formatted
602
- * @param string $separator The character that fills in spaces
603
- *
604
- * @return string Formatted text
605
- */
606
- protected function slugify( $text, $separator = '_' ) {
607
- $text = preg_replace( '~[^\\pL\d]+~u', $separator, $text );
608
- $text = trim( $text, $separator );
609
- $text = iconv( 'utf-8', 'us-ascii//TRANSLIT', $text );
610
- $text = strtolower( $text );
611
- $text = preg_replace( '~[^-\w]+~', '', $text );
612
- if ( empty( $text ) ) {
613
- return 'n-a';
614
- }
615
- return $text;
616
- }
617
-
618
- /**
619
- * Sorts one array using a second as a guide
620
- *
621
- * @param array $array Array to be sorted
622
- * @param array $order_array Guide array
623
- *
624
- * @return array Sorted array
625
- */
626
- protected function sort_array( $array, $order_array ) {
627
- $ordered = array();
628
- foreach ( $order_array as $key ) {
629
- if ( array_key_exists( $key, $array ) ) {
630
- $ordered[ $key ] = $array[ $key ];
631
- unset( $array[ $key ] );
632
- }
633
- }
634
- return $ordered + $array;
635
- }
636
-
637
- /**
638
- * Conditionally outputs an error in WordPress admin
639
- *
640
- * @param string $error The error to be output
641
- */
642
- public function submit_error( $error ) {
643
- $error = sprintf(
644
- '<div class="notice notice-error"><p>%s</p></div>',
645
- is_array( $error ) || is_object( $error ) ? '<pre>' . htmlspecialchars( print_r( $error, true ) ) . '</pre>' : $error
646
- );
647
- if ( empty( $this->points['admin_notices'] ) ) {
648
- $this->errors[] = $error;
649
- } else {
650
- echo $error;
651
- }
652
- }
653
-
654
- /**
655
- * Conditionally outputs a notice in WordPress admin
656
- *
657
- * @param string $notice The text to be output
658
- */
659
- public function submit_notice( $notice ) {
660
- $notice = sprintf(
661
- '<div class="notice notice-info"><p>%s</p></div>',
662
- is_array( $notice ) || is_object( $notice ) ? '<pre>' . htmlspecialchars( print_r( $notice, true ) ) . '</pre>' : $notice
663
- );
664
- if ( empty( $this->points['admin_notices'] ) ) {
665
- $this->notices[] = $notice;
666
- } else {
667
- echo $notice;
668
- }
669
- }
670
-
671
- /**
672
- * Validates the field data submitted to the class
673
- *
674
- * @param array $field Field array
675
- * @param string $page_key Array key of the associated page
676
- * @param string $section_key Array key of the associated section
677
- * @param string $field_key Array key of the field
678
- * @param string $page ID of the associated page
679
- * @param type $section ID of the associated section
680
- *
681
- * @return array The validated field array
682
- */
683
- protected function validate_field( $field, $page_key, $section_key, $field_key, $page, $section ) {
684
- // Label
685
- if ( empty( $field['title'] ) ) {
686
- $this->submit_error( 'Field parameter "title" is required' );
687
- }
688
-
689
- // ID
690
- if ( empty( $field['id'] ) ) {
691
- $field['id'] = $this->slugify( $field['title'] );
692
- }
693
-
694
- // Callback
695
- $field['callback'] = empty( $field['callback'] ) ? "add_settings_field|{$page_key}|{$section_key}|{$field_key}" : $field['callback'];
696
-
697
- // Page
698
- $field['page'] = $page;
699
-
700
- // Section
701
- $field['section'] = $section;
702
-
703
- // Type
704
- $field['type'] = empty( $field['type'] ) ? 'text' : $field['type'];
705
-
706
- // Title attribute
707
- $field['title_attr'] = empty( $field['title_attr'] ) ? $field['title'] : $field['title_attr'];
708
-
709
- // Choices
710
- if ( empty( $field['choices'] ) && in_array( $field['type'], array( 'radio', 'select' ) ) ) {
711
- $this->submit_error( 'Field parameter "choices" is required for the "radio" and "select" type' );
712
- }
713
-
714
- // Other attributes
715
- if ( !empty( $field['attributes'] ) ) {
716
- switch ( $field['type'] ) {
717
- case 'select':
718
- case 'textarea':
719
- $field['attributes'] = wp_parse_args( $field['attributes'], $this->attributes[ $field['type'] ] );
720
- break;
721
- default:
722
- $field['attributes'] = wp_parse_args( $field['attributes'], $this->attributes['input'] );
723
- }
724
- }
725
-
726
- // Making sure we haven't missed anything
727
- switch ( $field['type'] ) {
728
- case 'checkbox':
729
- $field = wp_parse_args( $field, $this->fields['checkbox'] );
730
- break;
731
- case 'color':
732
- case 'radio':
733
- case 'range':
734
- break;
735
- case 'date':
736
- $field['value'] = date( 'Y-m-d', strtotime( $field['value'] ) );
737
- $field = wp_parse_args( $field, $this->fields['text'] );
738
- break;
739
- case 'datetime':
740
- case 'datetime-local':
741
- $field['value'] = date( 'Y-m-d\TH:i:s', strtotime( $field['value'] ) );
742
- $field = wp_parse_args( $field, $this->fields['text'] );
743
- break;
744
- case 'month':
745
- $field['value'] = date( 'Y-m', strtotime( $field['value'] ) );
746
- $field = wp_parse_args( $field, $this->fields['text'] );
747
- break;
748
- case 'textarea':
749
- $field = wp_parse_args( $field, $this->fields[ $field['type'] ] );
750
- break;
751
- case 'time':
752
- $field['value'] = date( 'H:i:s', strtotime( $field['value'] ) );
753
- $field = wp_parse_args( $field, $this->fields['text'] );
754
- break;
755
- case 'week':
756
- $field['value'] = date( 'Y-\WW', strtotime( $field['value'] ) );
757
- $field = wp_parse_args( $field, $this->fields['text'] );
758
- break;
759
- case 'wp_editor':
760
- $field = wp_parse_args( $field, $this->fields['wp_editor'] );
761
- break;
762
- default:
763
- $field = wp_parse_args( $field, $this->fields['text'] );
764
- }
765
-
766
- return $field;
767
- }
768
-
769
- /**
770
- * Validates the information submitted to the class
771
- *
772
- * @param string $page_key Array key of the page
773
- * @param array $page Array of page parameters
774
- * @param string $parent_slug Menu slug of the parent page if there is one
775
- *
776
- * @return array Validated array of page parameters
777
- */
778
- protected function validate_page( $page_key, $page_params, $parent_slug = false ) {
779
- // Page title
780
- if ( empty( $page_params['page_title'] ) ) {
781
- $this->submit_error( 'Page parameter "page_title" is required' );
782
- }
783
-
784
- // Menu title
785
- if ( empty( $page_params['menu_title'] ) ) {
786
- $page_params['menu_title'] = $page_params['page_title'];
787
- }
788
-
789
- // Menu slug
790
- if ( empty( $page_params['menu_slug'] ) ) {
791
- // Basing it off the page title cause it's likely to be more unique than the menu title
792
- $page_params['menu_slug'] = $this->slugify( $page_params['page_title'] );
793
- }
794
-
795
- // Menu or submenu item?
796
- if ( empty( $page_params['parent_slug'] ) && !$parent_slug ) {
797
- $page_params['function'] = 'add_menu_page';
798
- } else {
799
- $page_params['function'] = 'add_submenu_page';
800
- $page_params['parent_slug'] = $parent_slug ? $parent_slug : $page_params['parent_slug'];
801
- }
802
-
803
- // Callback
804
- $page_params['callback'] = "{$page_params['function']}|{$page_key}";
805
-
806
- // Sanitize
807
- $page_params['sanitize'] = empty( $page_params['sanitize'] ) ? "register_setting|{$page_key}" : $page_params['sanitize'];
808
-
809
- // Make sure we haven't missed anything
810
- $page_params = wp_parse_args( $page_params, $this->defaults[ $page_params['function'] ] );
811
-
812
- // Subpages?
813
- if ( !empty( $page_params['subpages'] ) ) {
814
- foreach ( $page_params['subpages'] as $subpage_key => $subpage ) {
815
- $this->subpages[ $subpage_key ] = $this->validate_page( $subpage_key, $subpage, $page_params['menu_slug'] );
816
- }
817
- unset( $page_params['subpages'] );
818
- }
819
-
820
- // Sections?
821
- if ( !empty( $page_params['sections'] ) ) {
822
- foreach ( $page_params['sections'] as $section_key => $section_params ) {
823
- $page_params['sections'][ $section_key ] = $this->validate_section( $section_params, $page_key, $section_key, $page_params['menu_slug'] );
824
- }
825
- }
826
-
827
- return $page_params;
828
- }
829
-
830
- /**
831
- * Validates the section data submitted to the class
832
- *
833
- * @param array $section Section array
834
- * @param string $page_key Array key of the associated page
835
- * @param string $section_key Array key of the associated page
836
- * @param string $page ID of the associated page
837
- *
838
- * @return array Validated section array
839
- */
840
- protected function validate_section( $section, $page_key, $section_key, $page ) {
841
- // Title
842
- if ( empty( $section['title'] ) ) {
843
- $this->submit_error( 'Section parameter "title" is required' );
844
- }
845
-
846
- // ID
847
- if ( empty( $section['id'] ) ) {
848
- $section['id'] = $this->slugify( $section['title'] );
849
- }
850
-
851
- // Callback
852
- $section['callback'] = empty( $section['callback'] ) ? "add_settings_section|{$page_key}|{$section_key}" : $section['callback'];
853
-
854
- // Page
855
- $section['page'] = $page;
856
-
857
- // Fields?
858
- if ( !empty( $section['fields'] ) ) {
859
- foreach ( $section['fields'] as $field_key => $field_params ) {
860
- $section['fields'][ $field_key ] = $this->validate_field( $field_params, $page_key, $section_key, $field_key, $page, $section['id'] );
861
- }
862
- }
863
-
864
- return $section;
865
- }
866
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/common-functions.php CHANGED
@@ -17,7 +17,7 @@ $config_submenu = array(
17
  'type' => 'menu', // Required, menu or metabox
18
  'title' => 'Steroids for Elementor v' . OoohBoi_Steroids::VERSION, // options panel title
19
  'menu_title' => 'Steroids for Elementor', // admin menu title
20
- 'icon' => SFE_DIR_URL . 'img/ooohboi-poopart-icon.png',
21
  'id' => 'steroids_for_elementor', // Required, meta box id, unique per page, to save: get_option( id )
22
  'parent' => 'edit.php?post_type=steroids_for_elementor', // Parent page of plugin menu (default Settings [options-general.php])
23
  'submenu' => false,
@@ -249,15 +249,15 @@ $fields[] = array(
249
  'title' => esc_html__( 'Multiplier', 'ooohboi-steroids' ),
250
  'description' => sprintf( __( '%sBoost/reduce scrolling speed. 1 is the default.%s', 'ooohboi-steroids' ), '<span class="ob-option-desc">', '</span>' ),
251
  'type' => 'range',
252
- 'default' => '1',
253
  'min' => '0.1',
254
- 'max' => '10',
255
  'step' => '0.1',
256
  ),
257
  array(
258
  'id' => 'ob_allow_refresh',
259
  'title' => esc_html__( 'Refresh on resize?', 'ooohboi-steroids' ),
260
- 'description' => esc_html__( 'Things get messy on resize. That will do the page refresh upon the window resize/orientationchange.', 'ooohboi-steroids' ),
261
  'type' => 'checkbox',
262
  'default' => 'no',
263
  'style' => 'fancy',
17
  'type' => 'menu', // Required, menu or metabox
18
  'title' => 'Steroids for Elementor v' . OoohBoi_Steroids::VERSION, // options panel title
19
  'menu_title' => 'Steroids for Elementor', // admin menu title
20
+ 'icon' => SFE_DIR_URL . 'img/sfe-icon-WP-admin.png',
21
  'id' => 'steroids_for_elementor', // Required, meta box id, unique per page, to save: get_option( id )
22
  'parent' => 'edit.php?post_type=steroids_for_elementor', // Parent page of plugin menu (default Settings [options-general.php])
23
  'submenu' => false,
249
  'title' => esc_html__( 'Multiplier', 'ooohboi-steroids' ),
250
  'description' => sprintf( __( '%sBoost/reduce scrolling speed. 1 is the default.%s', 'ooohboi-steroids' ), '<span class="ob-option-desc">', '</span>' ),
251
  'type' => 'range',
252
+ 'default' => '0.5',
253
  'min' => '0.1',
254
+ 'max' => '3',
255
  'step' => '0.1',
256
  ),
257
  array(
258
  'id' => 'ob_allow_refresh',
259
  'title' => esc_html__( 'Refresh on resize?', 'ooohboi-steroids' ),
260
+ 'description' => esc_html__( 'Things get messy on resize. That will do the silent page refresh upon the window resize/orientationchange.', 'ooohboi-steroids' ),
261
  'type' => 'checkbox',
262
  'default' => 'no',
263
  'style' => 'fancy',
inc/exopite-simple-options/fields/backup.php CHANGED
@@ -66,7 +66,6 @@ if ( ! class_exists( 'Exopite_Simple_Options_Framework_Field_backup' ) ) {
66
  */
67
  function encode_string( $option ) {
68
  return json_encode( $option );
69
- // return rtrim( strtr( call_user_func( 'base' . '64' . '_encode', addslashes( gzcompress( serialize( $option ), 9 ) ) ), '+/', '-_' ), '=' );
70
  }
71
 
72
  /**
@@ -74,7 +73,6 @@ if ( ! class_exists( 'Exopite_Simple_Options_Framework_Field_backup' ) ) {
74
  */
75
  function decode_string( $option ) {
76
  return json_decode( $_POST['value'], true );
77
- // return unserialize( gzuncompress( stripslashes( call_user_func( 'base' . '64' . '_decode', rtrim( strtr( $option, '-_', '+/' ), '=' ) ) ) ) );
78
  }
79
 
80
  public static function enqueue( $args ) {
66
  */
67
  function encode_string( $option ) {
68
  return json_encode( $option );
 
69
  }
70
 
71
  /**
73
  */
74
  function decode_string( $option ) {
75
  return json_decode( $_POST['value'], true );
 
76
  }
77
 
78
  public static function enqueue( $args ) {
inc/img/sfe-icon-WP-admin.png ADDED
Binary file
inc/info/ob-landing.php CHANGED
@@ -10,6 +10,16 @@
10
 
11
  <div class="col-8">
12
 
 
 
 
 
 
 
 
 
 
 
13
  <h3>What's new in v1.7.3</h3>
14
  <ul>
15
  <li>
@@ -41,16 +51,6 @@
41
  </li>
42
  </ul>
43
 
44
- <h3>v1.7.2 reminder</h3>
45
- <ul>
46
- <li>
47
- Since the version 1.7.2 IMBOX and ICOBOX extensions bring the new responsive controls for the image/icon size, while the existing Override controls now include new 'vw' and 'vh' CSS units.
48
- </li>
49
- <li>
50
- From now on BREAKING BAD allows you to set the Column-link (clickable column).
51
- </li>
52
- </ul>
53
-
54
  </div>
55
 
56
  <div class="col-4">
10
 
11
  <div class="col-8">
12
 
13
+ <h3>What's new in v1.7.4</h3>
14
+ <ul>
15
+ <li>
16
+ <p>
17
+ There's nothing new when it comes to functionality except a few fixes and improvements to the previous release. For everyone experiencing that Sucuri malware warning, it came from the Exopite framework,
18
+ and was related to a couple of already commented/cancelled lines of code. These are removed now so everything should be OK.
19
+ </p>
20
+ </li>
21
+ </ul>
22
+
23
  <h3>What's new in v1.7.3</h3>
24
  <ul>
25
  <li>
51
  </li>
52
  </ul>
53
 
 
 
 
 
 
 
 
 
 
 
54
  </div>
55
 
56
  <div class="col-4">
lang/ooohboi-steroids.pot CHANGED
@@ -3,14 +3,14 @@ msgid ""
3
  msgstr ""
4
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
5
  "Project-Id-Version: OoohBoi Steroids for Elementor\n"
6
- "POT-Creation-Date: 2021-04-28 15:06+0200\n"
7
- "PO-Revision-Date: 2021-04-28 15:06+0200\n"
8
  "Last-Translator: \n"
9
  "Language-Team: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 2.4.2\n"
14
  "X-Poedit-Basepath: ..\n"
15
  "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
16
  "X-Poedit-WPHeader: ooohboi-steroids.php\n"
@@ -1965,8 +1965,8 @@ msgstr ""
1965
 
1966
  #: inc/common-functions.php:260
1967
  msgid ""
1968
- "Things get messy on resize. That will do the page refresh upon the window "
1969
- "resize/orientationchange."
1970
  msgstr ""
1971
 
1972
  #: inc/common-functions.php:271
3
  msgstr ""
4
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
5
  "Project-Id-Version: OoohBoi Steroids for Elementor\n"
6
+ "POT-Creation-Date: 2021-05-02 16:53+0200\n"
7
+ "PO-Revision-Date: 2021-05-02 16:53+0200\n"
8
  "Last-Translator: \n"
9
  "Language-Team: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 2.4.3\n"
14
  "X-Poedit-Basepath: ..\n"
15
  "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
16
  "X-Poedit-WPHeader: ooohboi-steroids.php\n"
1965
 
1966
  #: inc/common-functions.php:260
1967
  msgid ""
1968
+ "Things get messy on resize. That will do the silent page refresh upon the "
1969
+ "window resize/orientationchange."
1970
  msgstr ""
1971
 
1972
  #: inc/common-functions.php:271
ooohboi-steroids.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: OoohBoi Steroids for Elementor
4
  * Description: An awesome set of tools, options and settings that expand Elementor defaults. Instead of creating new Elementor Widgets, these act like an upgrade of existing options or the self-standing panels.
5
- * Version: 1.7.3
6
  * Author: OoohBoi
7
  * Author URI: https://www.youtube.com/c/OoohBoi
8
  * Text Domain: ooohboi-steroids
@@ -31,7 +31,7 @@ final class OoohBoi_Steroids {
31
  *
32
  * @var string The plugin version.
33
  */
34
- const VERSION = '1.7.3';
35
 
36
  /**
37
  * Minimum Elementor Version
@@ -345,7 +345,7 @@ final class OoohBoi_Steroids {
345
  }
346
  // -----------------------------
347
 
348
- wp_register_style( 'ooohboi-steroids-styles', plugins_url( 'assets/css/main.css', __FILE__ ), NULL, self::VERSION . '28042021' );
349
 
350
  }
351
 
@@ -365,7 +365,7 @@ final class OoohBoi_Steroids {
365
  // locomotive scroll
366
  if( 1 === self::$sfe_lib_locomotive ) {
367
  wp_register_script( 'locomotive-scroll-js', plugins_url( 'lib/locomotive_scroll/locomotive-scroll.min.js', __FILE__ ), [], self::VERSION . '28042021', true );
368
- wp_register_script( 'locomotive-scroll-ctrl', plugins_url( 'assets/js/ooohboi-libs-locomotion.js', __FILE__ ), [ 'locomotive-scroll-js' ], self::VERSION . '28042021', true );
369
  }
370
  // scroll trigger
371
  if( 1 === self::$sfe_lib_scroll_trigger ) {
2
  /**
3
  * Plugin Name: OoohBoi Steroids for Elementor
4
  * Description: An awesome set of tools, options and settings that expand Elementor defaults. Instead of creating new Elementor Widgets, these act like an upgrade of existing options or the self-standing panels.
5
+ * Version: 1.7.4
6
  * Author: OoohBoi
7
  * Author URI: https://www.youtube.com/c/OoohBoi
8
  * Text Domain: ooohboi-steroids
31
  *
32
  * @var string The plugin version.
33
  */
34
+ const VERSION = '1.7.4';
35
 
36
  /**
37
  * Minimum Elementor Version
345
  }
346
  // -----------------------------
347
 
348
+ wp_register_style( 'ooohboi-steroids-styles', plugins_url( 'assets/css/main.css', __FILE__ ), NULL, self::VERSION . '03052021' );
349
 
350
  }
351
 
365
  // locomotive scroll
366
  if( 1 === self::$sfe_lib_locomotive ) {
367
  wp_register_script( 'locomotive-scroll-js', plugins_url( 'lib/locomotive_scroll/locomotive-scroll.min.js', __FILE__ ), [], self::VERSION . '28042021', true );
368
+ wp_register_script( 'locomotive-scroll-ctrl', plugins_url( 'assets/js/ooohboi-libs-locomotion.js', __FILE__ ), [ 'locomotive-scroll-js' ], self::VERSION . '30042021', true );
369
  }
370
  // scroll trigger
371
  if( 1 === self::$sfe_lib_scroll_trigger ) {
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: page-builder, elementor, add-on, background-overlay, vertical text, ghost
4
  Donate link: https://www.paypal.me/ooohboi
5
  Requires at least: 5.0
6
  Tested up to: 5.7
7
- Stable tag: 1.7.3
8
  Requires PHP: 7.0
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0
@@ -104,7 +104,7 @@ The power of Locomotive Scroll is now available in Elementor too!
104
 
105
  == Upgrade Notice ==
106
 
107
- 1.7.3 - Beware of the changes to the language file!
108
 
109
  == Frequently Asked Questions ==
110
 
@@ -148,6 +148,12 @@ No, you don't. It'll work with both free version of Elementor and Elementor PRO.
148
 
149
  == Changelog ==
150
 
 
 
 
 
 
 
151
  = 1.7.3 =
152
  - New feature added, LOCOMOTION - Locomotive Scroll for Elementor
153
  - New Options panel for the plugin
4
  Donate link: https://www.paypal.me/ooohboi
5
  Requires at least: 5.0
6
  Tested up to: 5.7
7
+ Stable tag: 1.7.4
8
  Requires PHP: 7.0
9
  License: GPLv3
10
  License URI: http://www.gnu.org/licenses/gpl-3.0
104
 
105
  == Upgrade Notice ==
106
 
107
+ 1.7.4 - Beware of the changes to the language file!
108
 
109
  == Frequently Asked Questions ==
110
 
148
 
149
  == Changelog ==
150
 
151
+ = 1.7.4 =
152
+ - Added "silent" page refresh on window resize event to the Locomotive Scroll pages
153
+ - Fixed Sucuri malware warning
154
+ - Fixed laggy Locomotive Scroll Multiplier on Firefox
155
+ - LOCOMOTION - all the built-in "fade" classes now work normally with Sections and Columns
156
+
157
  = 1.7.3 =
158
  - New feature added, LOCOMOTION - Locomotive Scroll for Elementor
159
  - New Options panel for the plugin