├── .bowerrc ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── css │ └── main.css ├── js │ └── main.js └── vendor │ ├── jquery-timepicker │ ├── .bower.json │ ├── GPL-LICENSE.txt │ ├── MIT-LICENSE.txt │ ├── README.md │ ├── i18n │ │ ├── i18n.html │ │ ├── jquery.ui.timepicker-cs.js │ │ ├── jquery.ui.timepicker-de.js │ │ ├── jquery.ui.timepicker-es.js │ │ ├── jquery.ui.timepicker-fr.js │ │ ├── jquery.ui.timepicker-hr.js │ │ ├── jquery.ui.timepicker-hu.js │ │ ├── jquery.ui.timepicker-it.js │ │ ├── jquery.ui.timepicker-ja.js │ │ ├── jquery.ui.timepicker-mk.js │ │ ├── jquery.ui.timepicker-nl.js │ │ ├── jquery.ui.timepicker-pl.js │ │ ├── jquery.ui.timepicker-pt-BR.js │ │ ├── jquery.ui.timepicker-ru.js │ │ ├── jquery.ui.timepicker-sl.js │ │ ├── jquery.ui.timepicker-sv.js │ │ └── jquery.ui.timepicker-tr.js │ ├── include │ │ ├── jquery-1.9.0.min.js │ │ └── ui-1.10.0 │ │ │ ├── jquery.ui.core.min.js │ │ │ ├── jquery.ui.position.min.js │ │ │ ├── jquery.ui.tabs.min.js │ │ │ ├── jquery.ui.widget.min.js │ │ │ └── ui-lightness │ │ │ ├── images │ │ │ ├── ui-bg_diagonals-thick_18_b81900_40x40.png │ │ │ ├── ui-bg_diagonals-thick_20_666666_40x40.png │ │ │ ├── ui-bg_flat_10_000000_40x100.png │ │ │ ├── ui-bg_glass_100_f6f6f6_1x400.png │ │ │ ├── ui-bg_glass_100_fdf5ce_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_gloss-wave_35_f6a828_500x100.png │ │ │ ├── ui-bg_highlight-soft_100_eeeeee_1x100.png │ │ │ ├── ui-bg_highlight-soft_75_ffe45c_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_228ef1_256x240.png │ │ │ ├── ui-icons_ef8c08_256x240.png │ │ │ ├── ui-icons_ffd27a_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ │ └── jquery-ui-1.10.0.custom.min.css │ ├── index.html │ ├── jquery.ui.timepicker.css │ ├── jquery.ui.timepicker.js │ ├── legacy_1.2.6 │ │ ├── index.html │ │ ├── jquery-1.2.6.js │ │ ├── jquery.proxy.fix.js │ │ └── jquery.ui.1.6.all.js │ ├── tests │ │ ├── dialog.html │ │ └── jquery.ui.dialog.min.js │ └── timepicker.png │ └── jquery-ui │ ├── images │ ├── ui-bg_flat_30_cccccc_40x100.png │ ├── ui-bg_flat_50_5c5c5c_40x100.png │ ├── ui-bg_glass_20_555555_1x400.png │ ├── ui-bg_glass_40_0078a3_1x400.png │ ├── ui-bg_glass_40_ffc73d_1x400.png │ ├── ui-bg_gloss-wave_25_333333_500x100.png │ ├── ui-bg_highlight-soft_80_eeeeee_1x100.png │ ├── ui-bg_inset-soft_25_000000_1x100.png │ ├── ui-bg_inset-soft_30_f58400_1x100.png │ ├── ui-icons_222222_256x240.png │ ├── ui-icons_4b8e0b_256x240.png │ ├── ui-icons_a83300_256x240.png │ ├── ui-icons_cccccc_256x240.png │ └── ui-icons_ffffff_256x240.png │ └── jquery-ui.css ├── bower.json ├── changelog.txt ├── composer.json ├── composer.lock ├── phpcs.xml ├── settings └── example-settings.php ├── wp-settings-framework.php └── wpsf-test.php /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "assets/vendor" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | /vendor/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2012 Dev7studios 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WordPress Settings Framework 2 | ============================ 3 | 4 | The WordPress Settings Framework aims to take the pain out of creating settings pages for your WordPress plugins 5 | by effectively creating a wrapper around the WordPress settings API and making it super simple to create and maintain 6 | settings pages. 7 | 8 | This repo is actually a working plugin which demonstrates how to implement WPSF in your plugins. See `wpsf-test.php` 9 | for details. 10 | 11 | Setting Up Your Plugin 12 | ---------------------- 13 | 14 | 1. Create a folder "wp-settings-framework" in the root of your plugin folder, containing `wp-settings-framework.php` and the "assets" folder. 15 | 2. Create a "settings" folder in your plugin root. 16 | 3. Create a settings file in your new "settings" folder (e.g. `settings-general.php`) 17 | 18 | Now you can set up your plugin like: 19 | 20 | ```php 21 | class WPSFTest { 22 | /** 23 | * @var string 24 | */ 25 | private $plugin_path; 26 | 27 | /** 28 | * @var WordPressSettingsFramework 29 | */ 30 | private $wpsf; 31 | 32 | /** 33 | * WPSFTest constructor. 34 | */ 35 | function __construct() { 36 | $this->plugin_path = plugin_dir_path( __FILE__ ); 37 | 38 | // Include and create a new WordPressSettingsFramework 39 | require_once( $this->plugin_path . 'wp-settings-framework/wp-settings-framework.php' ); 40 | $this->wpsf = new WordPressSettingsFramework( $this->plugin_path . 'settings/settings-general.php', 'prefix_settings_general' ); 41 | 42 | // Add admin menu 43 | add_action( 'admin_menu', array( $this, 'add_settings_page' ), 20 ); 44 | 45 | // Add an optional settings validation filter (recommended) 46 | add_filter( $this->wpsf->get_option_group() . '_settings_validate', array( &$this, 'validate_settings' ) ); 47 | } 48 | 49 | /** 50 | * Add settings page. 51 | */ 52 | function add_settings_page() { 53 | $this->wpsf->add_settings_page( array( 54 | 'parent_slug' => 'woocommerce', 55 | 'page_title' => __( 'Page Title', 'text-domain' ), 56 | 'menu_title' => __( 'menu Title', 'text-domain' ), 57 | 'capability' => 'manage_woocommerce', 58 | ) ); 59 | } 60 | 61 | /** 62 | * Validate settings. 63 | * 64 | * @param $input 65 | * 66 | * @return mixed 67 | */ 68 | function validate_settings( $input ) { 69 | // Do your settings validation here 70 | // Same as $sanitize_callback from http://codex.wordpress.org/Function_Reference/register_setting 71 | return $input; 72 | } 73 | 74 | // ... 75 | } 76 | ``` 77 | 78 | Your settings values can be accessed like so: 79 | 80 | ```php 81 | // Get settings 82 | $this->wpsf->get_settings(); 83 | ``` 84 | 85 | This will get either the saved setting values, or the default values that you set in your settings file. 86 | 87 | Or by getting individual settings: 88 | 89 | ```php 90 | // Get individual setting 91 | $setting = wpsf_get_setting( 'prefix_settings_general', 'general', 'text' ); 92 | ``` 93 | 94 | 95 | The Settings Files 96 | ------------------ 97 | 98 | The settings files work by filling the global `$wpsf_settings` array with data in the following format: 99 | 100 | ```php 101 | $wpsf_settings[] = array( 102 | 'section_id' => 'general', // The section ID (required) 103 | 'section_title' => 'General Settings', // The section title (required) 104 | 'section_description' => 'Some intro description about this section.', // The section description (optional) 105 | 'section_order' => 5, // The order of the section (required) 106 | 'fields' => array( 107 | array( 108 | 'id' => 'text', 109 | 'title' => 'Text', 110 | 'desc' => 'This is a description.', 111 | 'placeholder' => 'This is a placeholder.', 112 | 'type' => 'text', 113 | 'default' => 'This is the default value' 114 | ), 115 | array( 116 | 'id' => 'select', 117 | 'title' => 'Select', 118 | 'desc' => 'This is a description.', 119 | 'type' => 'select', 120 | 'default' => 'green', 121 | 'choices' => array( 122 | 'red' => 'Red', 123 | 'green' => 'Green', 124 | 'blue' => 'Blue' 125 | ) 126 | ), 127 | 128 | // add as many fields as you need... 129 | 130 | ) 131 | ); 132 | ``` 133 | 134 | Valid `fields` values are: 135 | 136 | * `id` - Field ID 137 | * `title` - Field title 138 | * `desc` - Field description 139 | * `conditional_desc` - Array of conditional field value descriptions (for select) 140 | * `placeholder` - Field placeholder 141 | * `type` - Field type (text/password/textarea/select/radio/checkbox/checkboxes/color/file/editor/code_editor) 142 | * `default` - Default value (or selected option) 143 | * `choices` - Array of options (for select/radio/checkboxes) 144 | * `mimetype` - Any valid mime type accepted by Code Mirror for syntax highlighting (for code_editor) 145 | 146 | See `settings/example-settings.php` for an example of possible values. 147 | 148 | 149 | API Details 150 | ----------- 151 | 152 | new WordPressSettingsFramework( string $settings_file [, string $option_group = ''] ) 153 | 154 | Creates a new settings [option_group](http://codex.wordpress.org/Function_Reference/register_setting) based on a setttings file. 155 | 156 | * `$settings_file` - path to the settings file 157 | * `$option_group` - optional "option_group" override (by default this will be set to the basename of the settings file) 158 | 159 |
wpsf_get_setting( $option_group, $section_id, $field_id )
160 | 161 | Get a setting from an option group 162 | 163 | * `$option_group` - option group id. 164 | * `$section_id` - section id (change to `[{$tab_id}_{$section_id}]` when using tabs. 165 | * `$field_id` - field id. 166 | 167 |
wpsf_delete_settings( $option_group )
168 | 169 | Delete all the saved settings from a option group 170 | 171 | * `$option_group` - option group id 172 | 173 | Actions & Filters 174 | --------------- 175 | 176 | **Filters** 177 | 178 | * `wpsf_register_settings_[option_group]` - The filter used to register your settings. See `settings/example-settings.php` for an example. 179 | * `[option_group]_settings_validate` - Basically the `$sanitize_callback` from [register_setting](http://codex.wordpress.org/Function_Reference/register_setting). Use `$wpsf->get_option_group()` to get the option group id. 180 | * `wpsf_defaults_[option_group]` - Default args for a settings field 181 | 182 | **Actions** 183 | 184 | * `wpsf_before_field_[option_group]` - Before a field HTML is output 185 | * `wpsf_before_field_[option_group]_[field_id]` - Before a field HTML is output 186 | * `wpsf_after_field_[option_group]` - After a field HTML is output 187 | * `wpsf_after_field_[option_group]_[field_id]` - After a field HTML is output 188 | * `wpsf_before_settings_[option_group]` - Before settings form HTML is output 189 | * `wpsf_after_settings_[option_group]` - After settings form HTML is output 190 | * `wpsf_before_settings_fields_[option_group]` - Before settings form fields HTML is output (inside the `
`) 191 | * `wpsf_do_settings_sections_[option_group]` - Settings form fields HTMLoutput (inside the ``) 192 | * `wpsf_do_settings_sections_[option_group]` - Settings form fields HTMLoutput (inside the ``) 193 | * `wpsf_before_tab_links_[option_group]` - Before tabs HTML is output 194 | * `wpsf_after_tab_links_[option_group]` - After tabs HTML is output 195 | 196 | Credits 197 | ------- 198 | 199 | The WordPress Settings Framework was created by [Gilbert Pellegrom](http://gilbert.pellegrom.me) from [Dev7studios](http://dev7studios.com) and maintained by [James Kemp](https://jckemp.com) from [Iconic](https://iconicwp.com) 200 | 201 | Please contribute by [reporting bugs](https://github.com/jamesckemp/WordPress-Settings-Framework/issues) and submitting [pull requests](https://github.com/jamesckemp/WordPress-Settings-Framework/pulls). 202 | 203 | Want to say thanks? [Consider tipping me](https://www.paypal.me/jamesckemp). 204 | -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Settings page styles 3 | * 4 | * $. Tabs 5 | * $. Repeater 6 | * $. Fields 7 | * $. - Toggle 8 | * $. - Multifields 9 | * $. - Subtitle 10 | * $. Tables 11 | * $. Lists 12 | * $. Visual Checkbox and radio fields 13 | */ 14 | 15 | /* Main */ 16 | 17 | .wpsf-settings { 18 | margin: 0 0 0 -20px; 19 | } 20 | 21 | @media screen and (max-width: 782px) { 22 | .wpsf-settings { 23 | margin-left: -10px; 24 | } 25 | } 26 | 27 | .wpsf-settings__header { 28 | background: #fff; 29 | border-bottom: 1px solid #e2e4e7; 30 | padding: 10px 20px; 31 | height: 70px; 32 | box-sizing: border-box; 33 | display: flex; 34 | align-items: center; 35 | margin: 0; 36 | } 37 | 38 | .wpsf-settings__content { 39 | padding: 0 20px; 40 | } 41 | 42 | /* Nav */ 43 | 44 | .wpsf-nav { 45 | margin: 0 -20px; 46 | padding: 0 12px; 47 | list-style: none none outside; 48 | background: #fff; 49 | border-bottom: 1px solid #e2e4e7; 50 | display: flex; 51 | flex-wrap: nowrap; 52 | position: sticky; 53 | top: 32px; 54 | z-index: 100; 55 | align-items: center; 56 | } 57 | 58 | @media screen and (max-width: 782px) { 59 | .wpsf-nav { 60 | top: 46px; 61 | } 62 | } 63 | 64 | @media screen and (max-width: 600px) { 65 | .wpsf-nav { 66 | position: relative; 67 | top: 0; 68 | flex-direction: column; 69 | padding: 0; 70 | } 71 | } 72 | 73 | .wpsf-nav__item { 74 | display: inline-block; 75 | margin: 0 8px; 76 | padding: 0 4px 4px; 77 | position: relative; 78 | } 79 | 80 | @media screen and (max-width: 600px) { 81 | .wpsf-nav__item { 82 | padding-right: 0; 83 | padding-left: 0; 84 | margin: 0; 85 | width: 100%; 86 | text-align: center; 87 | border-top: 1px solid #e2e4e7; 88 | } 89 | 90 | .wpsf-nav__item:first-child { 91 | border-top: none; 92 | } 93 | } 94 | 95 | .wpsf-nav__item:after { 96 | content: ''; 97 | height: 0; 98 | transition: height 150ms ease-in-out; 99 | position: absolute; 100 | bottom: 0; 101 | left: 0; 102 | right: 0; 103 | backface-visibility: hidden; 104 | transform: translateZ(0); 105 | } 106 | 107 | .wpsf-nav__item--active:after { 108 | height: 4px; 109 | background: #2271b6; 110 | border-radius: 4px 4px 0 0; 111 | } 112 | 113 | @media screen and (max-width: 600px) { 114 | .wpsf-nav__item--active:after { 115 | border-radius: 0; 116 | } 117 | } 118 | 119 | .wpsf-nav__item-link { 120 | padding: 15px 0 13px; 121 | display: block; 122 | text-decoration: none; 123 | color: #000; 124 | white-space: nowrap; 125 | } 126 | 127 | .wpsf-nav__item-link:active, 128 | .wpsf-nav__item-link:focus { 129 | outline: none; 130 | box-shadow: none; 131 | color: #000; 132 | } 133 | 134 | .wpsf-nav__item-link:hover { 135 | color: #2271b6; 136 | } 137 | 138 | .wpsf-nav__item--active .wpsf-nav__item-link, 139 | .wpsf-nav__item--active .wpsf-nav__item-link:active, 140 | .wpsf-nav__item--active .wpsf-nav__item-link:focus, 141 | .wpsf-nav__item--active .wpsf-nav__item-link:hover { 142 | color: #2271b6; 143 | } 144 | 145 | .wpsf-nav__item--last { 146 | margin: 0 0 0 auto; 147 | padding: 0 8px; 148 | } 149 | 150 | @media screen and (max-width: 782px) { 151 | .wpsf-nav__item--last { 152 | display: none; 153 | } 154 | } 155 | 156 | /* Notices */ 157 | 158 | .notice { 159 | display: none !important; 160 | } 161 | 162 | .wpsf-notices { 163 | padding: 0; 164 | margin: 0; 165 | } 166 | 167 | .wpsf-notices h2 { 168 | display: none !important; 169 | } 170 | 171 | .wpsf-notices .notice { 172 | display: block !important; 173 | margin: 0 0 15px; 174 | } 175 | 176 | .wpsf-notices h2+.notice { 177 | margin-top: 20px; 178 | } 179 | 180 | .wpsf-notices .notice:last-child { 181 | margin-bottom: 20px; 182 | } 183 | 184 | /* Submit */ 185 | 186 | p.submit { 187 | padding-top: 0 !important; 188 | } 189 | 190 | /* $. Tabs */ 191 | 192 | .nav-tab-wrapper { 193 | min-height: 35px; 194 | } 195 | 196 | .wpsf-tab { 197 | display: none; 198 | } 199 | 200 | .wpsf-tab--active { 201 | display: block; 202 | } 203 | 204 | .wpsf-tab .postbox { 205 | margin: 20px 0; 206 | border-radius: 8px; 207 | border: none; 208 | background: #fff; 209 | } 210 | 211 | .wpsf-tab .postbox:after { 212 | content: ''; 213 | display: table; 214 | } 215 | 216 | .wpsf-tab .postbox h2 { 217 | padding: 15px 20px; 218 | border: none; 219 | margin: 0 0 10px; 220 | background: #23282d; 221 | color: #fff; 222 | -webkit-font-smoothing: antialiased; 223 | -moz-font-smoothing: antialiased; 224 | -o-font-smoothing: antialiased; 225 | font-smoothing: antialiased; 226 | font-size: 1.25em; 227 | } 228 | 229 | .wpsf-tab .postbox h2:first-child { 230 | border-radius: 8px 8px 0 0; 231 | } 232 | 233 | .wpsf-tab .postbox h3:first-child { 234 | margin-top: 0; 235 | } 236 | 237 | .js .wpsf-tab .postbox h3 { 238 | cursor: default; 239 | } 240 | 241 | .wpsf-tab .postbox table.form-table, 242 | .wpsf-tab .wpsf-section-description { 243 | margin: 0 20px; 244 | width: auto; 245 | } 246 | 247 | .wpsf-tab .postbox table.form-table { 248 | min-width: 80%; 249 | } 250 | 251 | .wpsf-tab .postbox table.form-table { 252 | margin-bottom: 10px; 253 | } 254 | 255 | .wpsf-tab .wpsf-section-description { 256 | margin: 30px 0 20px; 257 | padding: 0 30px 30px; 258 | box-sizing: border-box; 259 | font-size: 13px; 260 | line-height: 1.5; 261 | border-bottom: 1px solid #f1f1f1; 262 | } 263 | 264 | .wpsf-tab .wpsf-section-description h3 { 265 | font-size: 22px; 266 | max-width: 600px; 267 | } 268 | 269 | .wpsf-tab .wpsf-section-description p, 270 | .wpsf-tab .wpsf-section-description ol, 271 | .wpsf-tab .wpsf-section-description ul { 272 | font-size: 15px; 273 | max-width: 600px; 274 | margin-top: 1em; 275 | margin-bottom: 1em; 276 | } 277 | 278 | .wpsf-tab .wpsf-section-description ol, 279 | .wpsf-tab .wpsf-section-description ul { 280 | margin: 1em 0 2em 2em; 281 | } 282 | 283 | .wpsf-tab .wpsf-section-description p:first-of-type { 284 | font-size: 17px; 285 | } 286 | 287 | .wpsf-tab .wpsf-section-description :last-child { 288 | margin-bottom: 0; 289 | } 290 | 291 | .wpsf-tab a .dashicons { 292 | text-decoration: none; 293 | } 294 | 295 | @media screen and (max-width: 782px) { 296 | .wpsf-tab .wpsf-section-description { 297 | padding: 20px 0; 298 | } 299 | } 300 | 301 | /* $. Repeater */ 302 | 303 | .wpsf-group__row:first-child .wpsf-group__row-remove { 304 | display: none; 305 | } 306 | 307 | .wpsf-group__row td { 308 | border-bottom: 1px solid #ccd0d4; 309 | } 310 | 311 | .wpsf-group__row:last-child td { 312 | border-bottom: none; 313 | } 314 | 315 | .wpsf-group__row-index, 316 | .wpsf-group__row-actions { 317 | vertical-align: middle !important; 318 | } 319 | 320 | .wpsf-group__row-index { 321 | width: 25px; 322 | border-right: 1px solid #e5e5e5; 323 | } 324 | 325 | .wpsf-group__row-index span { 326 | text-align: center; 327 | display: inline-block; 328 | width: 25px; 329 | line-height: 25px; 330 | height: 25px; 331 | background: #e5e5e5; 332 | border-radius: 25px; 333 | box-shadow: inset 0px 1px #c5c5c5; 334 | font-size: 90%; 335 | font-weight: bold; 336 | } 337 | 338 | .wpsf-group__row-actions { 339 | border-left: 1px solid #e5e5e5; 340 | position: relative; 341 | width: 20px; 342 | } 343 | 344 | .wpsf-group__row-add { 345 | position: absolute; 346 | bottom: -10px; 347 | background: #fff; 348 | border-radius: 100%; 349 | } 350 | 351 | .wpsf-group__row-fields { 352 | padding: 0 !important; 353 | } 354 | 355 | .wpsf-group__field-wrapper { 356 | display: block; 357 | border-bottom: 1px solid #e5e5e5; 358 | padding: 15px 10px; 359 | } 360 | 361 | .wpsf-group__field-wrapper:last-child { 362 | border-bottom: none; 363 | } 364 | 365 | .wpsf-group__field-wrapper.wpsf-group__field-wrapper--hidden { 366 | display: none; 367 | } 368 | 369 | .wpsf-group__field-label { 370 | display: block; 371 | margin: 0 0 5px; 372 | font-weight: bold; 373 | } 374 | 375 | .wpsf-group__row-fields .regular-text, 376 | .wpsf-group__row-fields textarea { 377 | width: 100%; 378 | } 379 | 380 | @media screen and (max-width: 782px) { 381 | .wpsf-group__row-index span { 382 | margin: 4px 0 1px; 383 | } 384 | 385 | .wpsf-group__row td, 386 | .wpsf-group__row:last-child td { 387 | border: none; 388 | border-bottom: 1px solid #e5e5e5; 389 | } 390 | 391 | .wpsf-group__row td:last-child { 392 | border: none; 393 | } 394 | 395 | .wpsf-group__row-add, 396 | .wpsf-group__row-remove { 397 | position: relative; 398 | display: inline-block; 399 | bottom: auto; 400 | margin: 4px 10px 1px 0; 401 | } 402 | 403 | .wpsf-group__row-add span, 404 | .wpsf-group__row-remove span { 405 | font-size: 24px; 406 | width: 24px; 407 | height: 24px; 408 | } 409 | } 410 | 411 | /* $. Fields */ 412 | 413 | .wpsf-section input.hasDatepicker { 414 | background: #fff; 415 | } 416 | 417 | .wpsf-section input[type="checkbox"], 418 | .wpsf-section input[type="radio"] { 419 | vertical-align: text-bottom; 420 | } 421 | 422 | /* $. Toggle */ 423 | 424 | .wpsf-section label.switch { 425 | position: relative; 426 | display: inline-block; 427 | width: 52px; 428 | height: 26px; 429 | margin-top: -3px; 430 | } 431 | 432 | .wpsf-section label.switch input { 433 | opacity: 0; 434 | width: 0; 435 | height: 0; 436 | } 437 | 438 | .wpsf-section label.switch .slider { 439 | border-radius: 26px; 440 | position: absolute; 441 | cursor: pointer; 442 | top: 0; 443 | left: 0; 444 | right: 0; 445 | bottom: 0; 446 | background-color: #ccc; 447 | -webkit-transition: .2s; 448 | transition: .2s; 449 | } 450 | 451 | .wpsf-section label.switch .slider:before { 452 | border-radius: 50%; 453 | position: absolute; 454 | content: ""; 455 | height: 18px; 456 | width: 18px; 457 | left: 4px; 458 | bottom: 4px; 459 | background-color: white; 460 | -webkit-transition: .2s; 461 | transition: .2s; 462 | } 463 | 464 | .wpsf-section label.switch input:checked+.slider { 465 | background-color: #2196F3; 466 | } 467 | 468 | .wpsf-section label.switch input:checked+.slider:before { 469 | -webkit-transform: translateX(26px); 470 | -ms-transform: translateX(26px); 471 | transform: translateX(26px); 472 | } 473 | 474 | /* $. End Toggle */ 475 | 476 | @media screen and (max-width: 782px) { 477 | 478 | .wpsf-section input[type="checkbox"], 479 | .wpsf-section input[type="radio"] { 480 | vertical-align: middle; 481 | display: inline-block; 482 | margin-top: 0; 483 | } 484 | } 485 | 486 | /* $. Multifields */ 487 | 488 | .wpsf-multifields { 489 | overflow: hidden; 490 | width: 100%; 491 | } 492 | 493 | .wpsf-multifields__field { 494 | width: 25%; 495 | float: left; 496 | display: inline-block; 497 | padding-right: 10px; 498 | -webkit-box-sizing: border-box; 499 | -moz-box-sizing: border-box; 500 | box-sizing: border-box; 501 | } 502 | 503 | .wpsf-multifields__field input { 504 | max-width: 100%; 505 | width: 100%; 506 | } 507 | 508 | .wpsf-multifields__field span { 509 | font-weight: 400; 510 | display: block; 511 | font-size: 12px; 512 | color: #888; 513 | font-style: italic; 514 | margin: 10px 0 0; 515 | } 516 | 517 | @media screen and (max-width: 782px) { 518 | 519 | .wpsf-multifields__field span { 520 | margin: -10px 0 0; 521 | } 522 | 523 | } 524 | 525 | /* $. Field Label */ 526 | 527 | .wpsf-label { 528 | display: flex; 529 | align-items: center; 530 | gap: 4px; 531 | } 532 | 533 | .wpsf-label__link { 534 | line-height: 21px; 535 | } 536 | 537 | /* $. Subtitle */ 538 | 539 | .wpsf-subtitle, 540 | .wpsf-description { 541 | font-weight: 400; 542 | display: block; 543 | font-size: 12px !important; 544 | color: #888; 545 | font-style: italic; 546 | margin: 15px 0 0; 547 | } 548 | 549 | .wpsf-description { 550 | max-width: 380px; 551 | margin-top: 15px !important; 552 | } 553 | 554 | .wpsf-hide-description { 555 | display: none; 556 | } 557 | 558 | /* $. Import */ 559 | 560 | .wpsf-import__false_btn { 561 | position: relative; 562 | overflow: hidden; 563 | display: inline-block; 564 | } 565 | 566 | .wpsf-import input[type=file] { 567 | display: none; 568 | } 569 | 570 | .wpsf-import__file { 571 | position: relative; 572 | display: inline-block; 573 | width: 200px; 574 | overflow: hidden; 575 | } 576 | 577 | 578 | @media screen and (max-width: 782px) { 579 | .wpsf-subtitle { 580 | margin: 10px 0 15px; 581 | } 582 | } 583 | 584 | /* $. Tables */ 585 | 586 | .wpsf-section .form-table th, 587 | .wpsf-section .form-table td { 588 | vertical-align: top; 589 | } 590 | 591 | .wpsf-section .form-table td { 592 | padding: 20px 10px; 593 | } 594 | 595 | @media screen and (max-width: 782px) { 596 | .wpsf-section .form-table td { 597 | padding: 10px; 598 | } 599 | 600 | .wpsf-section .form-table>tbody>tr>td { 601 | padding-left: 0; 602 | padding-right: 0; 603 | } 604 | 605 | .wpsf-section .form-table>tbody>tr>td:last-child { 606 | padding-bottom: 20px; 607 | } 608 | } 609 | 610 | /* $. Lists */ 611 | 612 | .wpsf-list { 613 | margin: 0; 614 | padding: 0; 615 | list-style: none none outside; 616 | } 617 | 618 | @media screen and (max-width: 782px) { 619 | .wpsf-list--checkboxes li { 620 | min-height: 25px; 621 | } 622 | } 623 | 624 | .wpsf-list li:last-child { 625 | margin-bottom: 0; 626 | } 627 | 628 | 629 | .wpsf-visual-field--grid { 630 | display: grid; 631 | grid-gap: 5%; 632 | grid-row-gap: 18px; 633 | } 634 | 635 | 636 | /* Image Checkbox and radio fields */ 637 | .wpsf-visual-field--grid { 638 | display: flex; 639 | gap: 20px; 640 | } 641 | 642 | 643 | ul.wpsf-visual-field--image-checkboxes img { 644 | max-width: 100%; 645 | } 646 | 647 | 648 | ul.wpsf-visual-field--image-radio img { 649 | max-width: 100%; 650 | height: auto; 651 | display: block; 652 | margin: 0 auto; 653 | } 654 | 655 | .wpsf-visual-field__item { 656 | margin: 0; 657 | padding: 0; 658 | border-radius: 4px; 659 | border: 1px solid #c9c9cd; 660 | position: relative; 661 | } 662 | 663 | .wpsf-visual-field__item label { 664 | display: block; 665 | border-radius: 4px; 666 | cursor: pointer; 667 | user-select: none; 668 | } 669 | 670 | .wpsf-visual-field input[type=checkbox], 671 | .wpsf-visual-field input[type=radio] { 672 | display: inline-block; 673 | } 674 | 675 | .wpsf-visual-field__item--checked { 676 | box-shadow: 0 0.3px 0.5px rgba(0, 0, 0, 0.035), 0 2px 4px rgba(0, 0, 0, 0.07); 677 | border-color: #24242d; 678 | } 679 | 680 | .wpsf-visual-field__item--checked .wpsf-visual-field-image-radio__img_wrap { 681 | border-color: #24242d; 682 | } 683 | 684 | .wpsf-visual-field-image-radio__img_wrap { 685 | height: 135px; 686 | display: flex; 687 | border-bottom: 1px solid #c9c9cd; 688 | } 689 | 690 | .wpsf-visual-field__item-text { 691 | color: #1d2327; 692 | font-weight: bold; 693 | display: inline; 694 | } 695 | 696 | .wpsf-visual-field__item-footer { 697 | padding: 12px 19px; 698 | } -------------------------------------------------------------------------------- /assets/js/main.js: -------------------------------------------------------------------------------- 1 | (function( $, document ) { 2 | 3 | var wpsf = { 4 | 5 | cache: function() { 6 | wpsf.els = {}; 7 | wpsf.vars = {}; 8 | 9 | wpsf.els.tab_links = $('.wpsf-nav__item-link'); 10 | wpsf.els.submit_button = $( '.wpsf-button-submit' ); 11 | }, 12 | 13 | on_ready: function() { 14 | 15 | // on ready stuff here 16 | wpsf.cache(); 17 | wpsf.trigger_dynamic_fields(); 18 | wpsf.setup_groups(); 19 | wpsf.tabs.watch(); 20 | wpsf.watch_submit(); 21 | wpsf.control_groups(); 22 | wpsf.setup_visual_radio_checkbox_field(); 23 | wpsf.importer.init(); 24 | 25 | $( document.body ).on( 26 | 'change', 27 | 'input, select, textarea, .wpsf-visual-field input[type="radio"], .wpsf-visual-field input[type="checkbox"]', 28 | wpsf.control_groups 29 | ); 30 | }, 31 | 32 | /** 33 | * Trigger dynamic fields 34 | */ 35 | trigger_dynamic_fields: function() { 36 | 37 | wpsf.setup_timepickers(); 38 | wpsf.setup_datepickers(); 39 | wpsf.setup_selects(); 40 | }, 41 | 42 | /** 43 | * Setup the main tabs for the settings page 44 | */ 45 | tabs: { 46 | /** 47 | * Watch for tab clicks. 48 | */ 49 | watch: function() { 50 | var tab_id = wpsf.tabs.get_tab_id(); 51 | 52 | if ( tab_id ) { 53 | wpsf.tabs.set_active_tab( tab_id ); 54 | } 55 | 56 | wpsf.els.tab_links.on( 'click', function( e ) { 57 | // Show tab 58 | var tab_id = $( this ).attr( 'href' ); 59 | 60 | wpsf.tabs.set_active_tab( tab_id ); 61 | 62 | e.preventDefault(); 63 | } ); 64 | 65 | $( '.wsf-internal-link' ).click( wpsf.tabs.follow_link ); 66 | }, 67 | 68 | /** 69 | * Is storage available. 70 | */ 71 | has_storage: 'undefined' !== typeof ( Storage ), 72 | 73 | /** 74 | * Handle click on the Internal link. 75 | * 76 | * Format of link is #tab-id|field-id. Field-id can be skipped. 77 | * 78 | * @param {*} e 79 | * @returns 80 | */ 81 | follow_link: function ( e ) { 82 | e.preventDefault(); 83 | var href = $( this ).attr( 'href' ); 84 | var tab_id, parts, element_id; 85 | 86 | if ( href.indexOf( '#tab-' ) != 0 ) { 87 | return; 88 | } 89 | 90 | // has "|" i.e. element ID. 91 | if ( href.indexOf( '|' ) > 0 ) { 92 | parts = href.split( '|' ); 93 | tab_id = parts[ 0 ]; 94 | element_id = parts[ 1 ]; 95 | } else { 96 | tab_id = href; 97 | } 98 | 99 | wpsf.tabs.set_active_tab( tab_id ); 100 | 101 | if ( element_id ) { 102 | $('html, body').animate({scrollTop: $(`#${element_id}`).offset().top - 100 }, 'fast'); 103 | } 104 | }, 105 | 106 | /** 107 | * Store tab ID. 108 | * 109 | * @param tab_id 110 | */ 111 | set_tab_id: function( tab_id ) { 112 | if ( !wpsf.tabs.has_storage ) { 113 | return; 114 | } 115 | 116 | localStorage.setItem( wpsf.tabs.get_option_page() + '_wpsf_tab_id', tab_id ); 117 | }, 118 | 119 | /** 120 | * Get tab ID. 121 | * 122 | * @returns {boolean} 123 | */ 124 | get_tab_id: function() { 125 | // If the tab id is specified in the URL hash, use that. 126 | if ( window.location.hash ) { 127 | // Check if hash is a tab. 128 | if ( $( `.wpsf-nav a[href="${window.location.hash}"]` ).length ) { 129 | return window.location.hash; 130 | } 131 | } 132 | 133 | if ( !wpsf.tabs.has_storage ) { 134 | return false; 135 | } 136 | 137 | return localStorage.getItem( wpsf.tabs.get_option_page() + '_wpsf_tab_id' ); 138 | }, 139 | 140 | /** 141 | * Set active tab. 142 | * 143 | * @param tab_id 144 | */ 145 | set_active_tab: function( tab_id ) { 146 | var $tab = $( tab_id ), 147 | $tab_link = $( '.wpsf-nav__item-link[href="' + tab_id + '"]' ); 148 | 149 | if ( $tab.length <= 0 || $tab_link.length <= 0 ) { 150 | // Reset to first available tab. 151 | $tab_link = $( '.wpsf-nav__item-link' ).first(); 152 | tab_id = $tab_link.attr( 'href' ); 153 | $tab = $( tab_id ); 154 | } 155 | 156 | // Set tab link active class 157 | wpsf.els.tab_links.parent().removeClass( 'wpsf-nav__item--active' ); 158 | $( 'a[href="' + tab_id + '"]' ).parent().addClass( 'wpsf-nav__item--active' ); 159 | 160 | // Show tab 161 | $( '.wpsf-tab' ).removeClass( 'wpsf-tab--active' ); 162 | $tab.addClass( 'wpsf-tab--active' ); 163 | 164 | wpsf.tabs.set_tab_id( tab_id ); 165 | }, 166 | 167 | /** 168 | * Get unique option page name. 169 | * 170 | * @returns {jQuery|string|undefined} 171 | */ 172 | get_option_page: function() { 173 | return $( 'input[name="option_page"]' ).val(); 174 | } 175 | }, 176 | 177 | /** 178 | * Set up timepickers 179 | */ 180 | setup_timepickers: function() { 181 | 182 | $( '.timepicker' ).not( '.hasTimepicker' ).each( function() { 183 | 184 | var timepicker_args = $( this ).data( 'timepicker' ); 185 | 186 | // It throws an error if empty string is passed. 187 | if ( '' === timepicker_args ) { 188 | timepicker_args = {}; 189 | } 190 | 191 | $( this ).timepicker( timepicker_args ); 192 | 193 | } ); 194 | 195 | }, 196 | 197 | /** 198 | * Set up timepickers 199 | */ 200 | setup_datepickers: function() { 201 | $( document ).on( 'focus', '.datepicker:not(.hasTimepicker)', function() { 202 | var datepicker_args = $( this ).data( 'datepicker' ); 203 | // It throws an error if empty string is passed. 204 | if ( '' === datepicker_args ) { 205 | datepicker_args = {}; 206 | } 207 | $( this ).datepicker( datepicker_args ); 208 | 209 | } ); 210 | 211 | // Empty altField if datepicker field is emptied. 212 | $( document ).on( 'change', '.datepicker', function(){ 213 | var datepicker = $( this ).data( 'datepicker' ); 214 | 215 | if ( ! $( this ).val() && datepicker.settings && datepicker.settings.altField ) { 216 | $( datepicker.settings.altField ).val( '' ); 217 | } 218 | }); 219 | }, 220 | 221 | /** 222 | * Set up selects 223 | */ 224 | setup_selects: function() { 225 | // Show/Hide descriptions based on selected value. 226 | $( document ).on( 'change', '.form-table select', function() { 227 | var value = $(this).val(); 228 | $(this).siblings( '.wpsf-description' ).hide(); 229 | $(this).siblings( `.wpsf-description[data-value="${value}"]` ).show(); 230 | }); 231 | }, 232 | 233 | /** 234 | * Setup repeatable groups 235 | */ 236 | setup_groups: function() { 237 | wpsf.reindex_groups(); 238 | 239 | // add row 240 | 241 | $( document ).on( 'click', '.wpsf-group__row-add', function() { 242 | 243 | var $group = $( this ).closest( '.wpsf-group' ), 244 | $row = $( this ).closest( '.wpsf-group__row' ), 245 | template_name = $( this ).data( 'template' ), 246 | $template = $( $( '#' + template_name ).html() ); 247 | 248 | $template.find( '.wpsf-group__row-id' ).val( wpsf.generate_random_id() ); 249 | 250 | $row.after( $template ); 251 | 252 | wpsf.reindex_group( $group ); 253 | 254 | wpsf.trigger_dynamic_fields(); 255 | 256 | $row.trigger('wpsfGroupRowAdded', [$row]); 257 | 258 | return false; 259 | 260 | } ); 261 | 262 | // remove row 263 | 264 | $( document ).on( 'click', '.wpsf-group__row-remove', function() { 265 | 266 | var $group = jQuery( this ).closest( '.wpsf-group' ), 267 | $row = jQuery( this ).closest( '.wpsf-group__row' ); 268 | 269 | $row.remove(); 270 | 271 | wpsf.reindex_group( $group ); 272 | 273 | return false; 274 | 275 | } ); 276 | 277 | }, 278 | 279 | /** 280 | * Generate random ID. 281 | * 282 | * @returns {string} 283 | */ 284 | generate_random_id: function() { 285 | return ( 286 | Number( String( Math.random() ).slice( 2 ) ) + 287 | Date.now() + 288 | Math.round( performance.now() ) 289 | ).toString( 36 ); 290 | }, 291 | 292 | /** 293 | * Reindex all groups. 294 | */ 295 | reindex_groups: function() { 296 | var $groups = jQuery( '.wpsf-group' ); 297 | 298 | if ( $groups.length <= 0 ) { 299 | return; 300 | } 301 | 302 | $groups.each( function( index, group ) { 303 | wpsf.reindex_group( jQuery( group ) ); 304 | } ); 305 | }, 306 | 307 | /** 308 | * Reindex a group of repeatable rows 309 | * 310 | * @param arr $group 311 | */ 312 | reindex_group: function( $group ) { 313 | var reindex_attributes = [ 'class', 'id', 'name', 'data-datepicker' ]; 314 | 315 | if ( 1 === $group.find( ".wpsf-group__row" ).length ) { 316 | $group.find( ".wpsf-group__row-remove" ).hide(); 317 | } else { 318 | $group.find( ".wpsf-group__row-remove" ).show(); 319 | } 320 | 321 | $group.find( ".wpsf-group__row" ).each( function( index ) { 322 | 323 | $( this ).removeClass( 'alternate' ); 324 | 325 | if ( index % 2 == 0 ) { 326 | $( this ).addClass( 'alternate' ); 327 | } 328 | 329 | $( this ).find( 'input, select' ).each( function() { 330 | var this_input = this, 331 | name = jQuery( this ).attr( 'name' ); 332 | 333 | if ( typeof name !== typeof undefined && name !== false ) { 334 | $( this_input ).attr( 'name', name.replace( /\[\d+\]/, '[' + index + ']' ) ); 335 | } 336 | 337 | $.each( this_input.attributes, function() { 338 | if ( this.name && this_input && $.inArray( this.name, reindex_attributes ) > -1 ) { 339 | $( this_input ).attr( this.name, this.value.replace( /\_\d+\_/, '_' + index + '_' ) ); 340 | } 341 | } ); 342 | } ); 343 | 344 | $( this ).find( '.wpsf-group__row-index span' ).html( index ); 345 | 346 | } ); 347 | }, 348 | 349 | /** 350 | * Watch submit click. 351 | */ 352 | watch_submit: function() { 353 | wpsf.els.submit_button.on( 'click', function() { 354 | var $button = $( this ), 355 | $wrapper = $button.closest( '.wpsf-settings' ), 356 | $form = $wrapper.find( 'form' ).first(); 357 | 358 | $form.submit(); 359 | } ); 360 | }, 361 | 362 | /** 363 | * Dynamic control groups. 364 | */ 365 | control_groups: function() { 366 | // If show if, hide by default. 367 | $( '.show-if' ).each( function( index ) { 368 | var element = $( this ), 369 | parent_tag = element.parent().prop( 'nodeName' ).toLowerCase(); 370 | 371 | 372 | // Field. 373 | if ( 'td' === parent_tag || 'label' === parent_tag || wpsf.is_visual_field( element ) ) { 374 | element.closest( 'tr' ).hide(); 375 | 376 | wpsf.maybe_show_element( element, function() { 377 | element.closest( 'tr' ).show(); 378 | } ); 379 | } 380 | 381 | // Tab. 382 | if ( 'li' === parent_tag ) { 383 | element.closest( 'li' ).hide(); 384 | 385 | wpsf.maybe_show_element( element, function() { 386 | element.closest( 'li' ).show(); 387 | } ); 388 | } 389 | 390 | // Section. 391 | if ( 'div' === parent_tag && ! wpsf.is_visual_field( element ) ) { 392 | element.prev().hide(); 393 | element.next().hide(); 394 | if ( element.next().hasClass( 'wpsf-section-description' ) ) { 395 | element.next().next().hide(); 396 | } 397 | 398 | wpsf.maybe_show_element( element, function() { 399 | element.prev().show(); 400 | element.next().show(); 401 | if ( element.next().hasClass( 'wpsf-section-description' ) ) { 402 | element.next().next().show(); 403 | } 404 | } ); 405 | } 406 | } ); 407 | 408 | // If hide if, show by default. 409 | $( '.hide-if' ).each( function( index ) { 410 | var element = $( this ), 411 | parent_tag = element.parent().prop( 'nodeName' ).toLowerCase(); 412 | 413 | // Field. 414 | if ( 'td' === parent_tag || 'label' === parent_tag || wpsf.is_visual_field( element ) ) { 415 | element.closest( 'tr' ).show(); 416 | 417 | wpsf.maybe_hide_element( element, function() { 418 | element.closest( 'tr' ).hide(); 419 | } ); 420 | } 421 | 422 | // Tab. 423 | if ( 'li' === parent_tag ) { 424 | element.closest( 'li' ).show(); 425 | 426 | wpsf.maybe_hide_element( element, function() { 427 | element.closest( 'li' ).hide(); 428 | } ); 429 | } 430 | 431 | // Section. 432 | if ( 'div' === parent_tag && ! wpsf.is_visual_field( element ) ) { 433 | element.prev().show(); 434 | element.next().show(); 435 | if ( element.next().hasClass( 'wpsf-section-description' ) ) { 436 | element.next().next().show(); 437 | } 438 | 439 | wpsf.maybe_hide_element( element, function() { 440 | element.prev().hide(); 441 | element.next().hide(); 442 | if ( element.next().hasClass( 'wpsf-section-description' ) ) { 443 | element.next().next().hide(); 444 | } 445 | } ); 446 | } 447 | } ); 448 | }, 449 | 450 | /** 451 | * Is the element part of a visual field? 452 | * 453 | * @param {object} element Element. 454 | */ 455 | is_visual_field: function( element ) { 456 | return element.parent().hasClass( 'wpsf-visual-field__item-footer' ); 457 | }, 458 | 459 | /** 460 | * Maybe Show Element. 461 | * 462 | * @param {object} element Element. 463 | * @param {function} callback Callback. 464 | */ 465 | maybe_show_element: function( element, callback ) { 466 | var classes = element.attr( 'class' ).split( /\s+/ ); 467 | var controllers = classes.filter( function( item ) { 468 | return item.includes( 'show-if--' ); 469 | }); 470 | 471 | Array.from( controllers ).forEach( function( control_group ) { 472 | var item = control_group.replace( 'show-if--', '' ); 473 | if ( item.includes( '&&' ) ) { 474 | var and_group = item.split( '&&' ); 475 | var show_item = true; 476 | Array.from( and_group ).forEach( function( and_item ) { 477 | if ( ! wpsf.get_show_item_bool( show_item, and_item ) ) { 478 | show_item = false; 479 | } 480 | }); 481 | 482 | if ( show_item ) { 483 | callback(); 484 | return; 485 | } 486 | } else { 487 | var show_item = true; 488 | show_item = wpsf.get_show_item_bool( show_item, item ); 489 | 490 | if ( show_item ) { 491 | callback(); 492 | return; 493 | } 494 | } 495 | }); 496 | }, 497 | 498 | /** 499 | * Maybe Hide Element. 500 | * 501 | * @param {object} element Element. 502 | * @param {function} callback Callback. 503 | */ 504 | maybe_hide_element: function( element, callback ) { 505 | var classes = element.attr( 'class' ).split( /\s+/ ); 506 | var controllers = classes.filter( function( item ) { 507 | return item.includes( 'hide-if--' ); 508 | }); 509 | 510 | Array.from( controllers ).forEach( function( control_group ) { 511 | var item = control_group.replace( 'hide-if--', '' ); 512 | if ( item.includes( '&&' ) ) { 513 | var and_group = item.split( '&&' ); 514 | var hide_item = true; 515 | Array.from( and_group ).forEach( function( and_item ) { 516 | if ( ! wpsf.get_show_item_bool( hide_item, and_item ) ) { 517 | hide_item = false; 518 | } 519 | }); 520 | 521 | if ( hide_item ) { 522 | callback(); 523 | return; 524 | } 525 | } else { 526 | var hide_item = true; 527 | hide_item = wpsf.get_show_item_bool( hide_item, item ); 528 | 529 | if ( hide_item ) { 530 | callback(); 531 | return; 532 | } 533 | } 534 | }); 535 | }, 536 | 537 | /** 538 | * Get Show Item Bool. 539 | * 540 | * @param {bool} show Boolean. 541 | * @param {object} item Element. 542 | * @returns {bool} 543 | */ 544 | get_show_item_bool: function( show = true, item ) { 545 | var split = item.split( '===' ); 546 | var control = split[0]; 547 | var values = split[1].split( '||' ); 548 | var control_value = wpsf.get_controller_value( control, values ); 549 | 550 | if ( ! values.includes( control_value ) ) { 551 | show = ! show; 552 | } 553 | 554 | return show; 555 | }, 556 | 557 | /** 558 | * Return the control value. 559 | */ 560 | get_controller_value: function( id, values ) { 561 | var control = $( '#' + id ); 562 | 563 | // This may be an image_radio field. 564 | if ( ! control.length && values.length ) { 565 | control = $( '#' + id + '_' + values[0] ); 566 | } 567 | 568 | if ( control.length && ( 'checkbox' === control.attr( 'type' ) || 'radio' === control.attr( 'type' ) ) ) { 569 | control = ( control.is( ':checked' ) ) ? control : false; 570 | } 571 | 572 | var value = ( control.length ) ? control.val() : 'undefined'; 573 | 574 | if ( typeof value === 'undefined' ) { 575 | value = ''; 576 | } 577 | 578 | return value.toString(); 579 | }, 580 | 581 | /** 582 | * Add checked class when radio button changes. 583 | */ 584 | setup_visual_radio_checkbox_field: function() { 585 | var checked_class = 'wpsf-visual-field__item--checked'; 586 | 587 | $( document ).on( 'change', '.wpsf-visual-field input[type="radio"], .wpsf-visual-field input[type="checkbox"]', function() { 588 | var $this = $( this ), 589 | $list = $this.closest( '.wpsf-visual-field' ), 590 | $list_item = $this.closest( '.wpsf-visual-field__item' ), 591 | $checked = $list.find( '.' + checked_class ), 592 | is_multi_select = $list.hasClass( 'wpsf-visual-field--image-checkboxes' ); 593 | 594 | if ( is_multi_select ) { 595 | if ( $this.prop( 'checked' ) ) { 596 | $list_item.addClass( checked_class ); 597 | } else { 598 | $list_item.removeClass( checked_class ); 599 | } 600 | } else { 601 | $checked.removeClass( checked_class ); 602 | $list_item.addClass( checked_class ); 603 | } 604 | 605 | } ); 606 | }, 607 | 608 | /** 609 | * Import related functions. 610 | */ 611 | importer: { 612 | init: function () { 613 | 614 | $( '.wpsf-import__button' ).click( function () { 615 | $( this ).parent().find( '.wpsf-import__file_field' ).trigger( 'click' ); 616 | } ); 617 | 618 | $( ".wpsf-import__file_field" ).change( function ( e ) { 619 | $this = $( this ); 620 | $td = $this.closest( 'td' ); 621 | 622 | var file_field = $this.get( 0 ), 623 | settings = "", 624 | wpsf_import_nonce = $td.find( '.wpsf_import_nonce' ).val(); 625 | wpsf_import_option_group = $td.find( '.wpsf_import_option_group' ).val(); 626 | 627 | 628 | if ( 'undefined' === typeof file_field.files[ 0 ] ) { 629 | alert( wpsf_vars.select_file ); 630 | return; 631 | } 632 | 633 | if ( ! confirm( 'Are you sure you want to override existing setting?' ) ) { 634 | return; 635 | } 636 | 637 | wpsf.importer.read_file_text( file_field.files[ 0 ], function ( content ) { 638 | try { 639 | JSON.parse( content ); 640 | settings = content; 641 | } catch { 642 | settings = false; 643 | alert( wpsf_vars.invalid_file ); 644 | } 645 | 646 | if ( !settings ) { 647 | return; 648 | } 649 | 650 | $td.find( '.spinner' ).addClass( 'is-active' ); 651 | // Run an ajax call to save settings. 652 | $.ajax( { 653 | url: 'admin-ajax.php', 654 | type: 'POST', 655 | data: { 656 | action: 'wpsf_import_settings', 657 | settings: settings, 658 | option_group: wpsf_import_option_group, 659 | _wpnonce: wpsf_import_nonce 660 | }, 661 | success: function ( response ) { 662 | if ( response.success ) { 663 | location.reload(); 664 | } else { 665 | alert( wpsf_vars.something_went_wrong ); 666 | } 667 | 668 | $td.find( '.spinner' ).removeClass( 'is-active' ); 669 | } 670 | } ); 671 | } ); 672 | } ); 673 | }, 674 | 675 | /** 676 | * Read File text. 677 | * 678 | * @param string File input. 679 | * @param finction Callback function. 680 | */ 681 | read_file_text( file, callback ) { 682 | const reader = new FileReader(); 683 | reader.readAsText(file); 684 | reader.onload = () => { 685 | callback(reader.result); 686 | }; 687 | } 688 | } 689 | }; 690 | 691 | $( document ).ready( wpsf.on_ready ); 692 | 693 | // Expose WPSF methods for use elsewhere. 694 | window.wpsf = wpsf; 695 | 696 | }( jQuery, document )); 697 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-timepicker", 3 | "homepage": "https://github.com/fgelinas/timepicker", 4 | "_release": "883bb2cd94", 5 | "_resolution": { 6 | "type": "branch", 7 | "branch": "master", 8 | "commit": "883bb2cd94ce65bc2a0a707b0c5911baf6de4ad4" 9 | }, 10 | "_source": "https://github.com/fgelinas/timepicker.git", 11 | "_target": "*", 12 | "_originalSource": "jquery-timepicker" 13 | } -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/GPL-LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES.""'''''' 279 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/MIT-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 John Resig, http://jquery.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/README.md: -------------------------------------------------------------------------------- 1 | jQuery UI Timepicker by François Gélinas 2 | ======================================== 3 | 4 | What 5 | ---- 6 | This is a jQuery UI time picker plugin build to match with other official jQuery UI widgets. 7 | Based on the existing date picker, it will blend nicely with your form and use your selected jQuery UI theme. 8 | The plugin is very easy to integrate in your form for you time (hours / minutes) inputs. 9 | 10 | Why 11 | --- 12 | I built this plugin because I could not find a plugin that did what I needed. 13 | 14 | Doc 15 | --- 16 | Examples are available on the main page at [http://fgelinas.com/code/timepicker](http://fgelinas.com/code/timepicker) 17 | Most option parameters are documented at [http://fgelinas.com/code/timepicker/#usage](http://fgelinas.com/code/timepicker/#usage) 18 | 19 | Requirements 20 | ------------ 21 | Work with jQuery 1.5.1 and more, also require jQuery UI core. 22 | There is a legacy version of the plugin made to work with older jQuery 1.2.6 and UI 1.6 at [http://fgelinas.com/code/timepicker/#get_timepicker](http://fgelinas.com/code/timepicker/#get_timepicker) 23 | 24 | Licenses 25 | -------- 26 | The plugin is licensed under the [MIT](https://github.com/fgelinas/timepicker/blob/master/MIT-LICENSE.txt) and [GPL](https://github.com/fgelinas/timepicker/blob/master/GPL-LICENSE.txt) licenses. 27 | 28 | Other Stuff 29 | ----------- 30 | There is a jsFiddle page [here](http://jsfiddle.net/fgelinas/R6jLt/) with basic implementation for testing. -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/i18n.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Internationalisation page for the jquery ui timepicker 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 65 | 66 | 67 | 87 | 88 |
89 | 90 |
91 | 92 |
93 | 94 | List of localisations : 95 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-cs.js: -------------------------------------------------------------------------------- 1 | /* Czech initialisation for the timepicker plugin */ 2 | /* Written by David Spohr (spohr.david at gmail). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['cs'] = { 5 | hourText: 'Hodiny', 6 | minuteText: 'Minuty', 7 | amPmText: ['dop.', 'odp.'] , 8 | closeButtonText: 'Zavřít', 9 | nowButtonText: 'Nyní', 10 | deselectButtonText: 'Odoznačit' } 11 | $.timepicker.setDefaults($.timepicker.regional['cs']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-de.js: -------------------------------------------------------------------------------- 1 | /* German initialisation for the timepicker plugin */ 2 | /* Written by Lowie Hulzinga. */ 3 | jQuery(function($){ 4 | $.timepicker.regional['de'] = { 5 | hourText: 'Stunde', 6 | minuteText: 'Minuten', 7 | amPmText: ['AM', 'PM'] , 8 | closeButtonText: 'Beenden', 9 | nowButtonText: 'Aktuelle Zeit', 10 | deselectButtonText: 'Wischen' } 11 | $.timepicker.setDefaults($.timepicker.regional['de']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-es.js: -------------------------------------------------------------------------------- 1 | /* Spanish initialisation for the jQuery time picker plugin. */ 2 | /* Writen by Jandro González (agonzalezalves@gmail.com) */ 3 | jQuery(function($){ 4 | $.timepicker.regional['es'] = { 5 | hourText: 'Hora', 6 | minuteText: 'Minuto', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Aceptar', 9 | nowButtonText: 'Ahora', 10 | deselectButtonText: 'Deseleccionar' } 11 | $.timepicker.setDefaults($.timepicker.regional['es']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-fr.js: -------------------------------------------------------------------------------- 1 | /* French initialisation for the jQuery time picker plugin. */ 2 | /* Written by Bernd Plagge (bplagge@choicenet.ne.jp), 3 | Francois Gelinas (frank@fgelinas.com) */ 4 | jQuery(function($){ 5 | $.timepicker.regional['fr'] = { 6 | hourText: 'Heures', 7 | minuteText: 'Minutes', 8 | amPmText: ['AM', 'PM'], 9 | closeButtonText: 'Fermer', 10 | nowButtonText: 'Maintenant', 11 | deselectButtonText: 'Désélectionner' } 12 | $.timepicker.setDefaults($.timepicker.regional['fr']); 13 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-hr.js: -------------------------------------------------------------------------------- 1 | /* Croatian/Bosnian initialisation for the timepicker plugin */ 2 | /* Written by Rene Brakus (rene.brakus@infobip.com). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['hr'] = { 5 | hourText: 'Sat', 6 | minuteText: 'Minuta', 7 | amPmText: ['Prijepodne', 'Poslijepodne'], 8 | closeButtonText: 'Zatvoriti', 9 | nowButtonText: 'Sada', 10 | deselectButtonText: 'Poništite'} 11 | 12 | $.timepicker.setDefaults($.timepicker.regional['hr']); 13 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-hu.js: -------------------------------------------------------------------------------- 1 | /* Hungarian initialisation for the timepicker plugin */ 2 | /* Written by Bálint Dávid Tarcsa. */ 3 | jQuery(function($){ 4 | $.timepicker.regional['hu'] = { 5 | hourText: 'Óra', 6 | minuteText: 'Perc', 7 | amPmText: ['De.', 'Du.'] , 8 | closeButtonText: 'Kész', 9 | nowButtonText: 'Most', 10 | deselectButtonText: 'Törlés' } 11 | $.timepicker.setDefaults($.timepicker.regional['hu']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-it.js: -------------------------------------------------------------------------------- 1 | /* Italian initialisation for the jQuery time picker plugin. */ 2 | /* Written by Serge Margarita (serge.margarita@gmail.com) */ 3 | jQuery(function($){ 4 | $.timepicker.regional['it'] = { 5 | hourText: 'Ore', 6 | minuteText: 'Minuti', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Chiudi', 9 | nowButtonText: 'Adesso', 10 | deselectButtonText: 'Svuota' } 11 | $.timepicker.setDefaults($.timepicker.regional['it']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-ja.js: -------------------------------------------------------------------------------- 1 | /* Japanese initialisation for the jQuery time picker plugin. */ 2 | /* Written by Bernd Plagge (bplagge@choicenet.ne.jp). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['ja'] = { 5 | hourText: '時間', 6 | minuteText: '分', 7 | amPmText: ['午前', '午後'], 8 | closeButtonText: '閉じる', 9 | nowButtonText: '現時', 10 | deselectButtonText: '選択解除' } 11 | $.timepicker.setDefaults($.timepicker.regional['ja']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-mk.js: -------------------------------------------------------------------------------- 1 | /* Macedonian initialisation for the timepicker plugin */ 2 | /* Written by Stojance Panov. */ 3 | jQuery(function($){ 4 | $.timepicker.regional['mk'] = { 5 | hourText: 'Час', 6 | minuteText: 'Минути', 7 | amPmText: ['Претпладне', 'Попладне'], 8 | closeButtonText: 'Затвори', 9 | nowButtonText: 'Сега', 10 | deselectButtonText: 'Поништи'} 11 | 12 | $.timepicker.setDefaults($.timepicker.regional['mk']); 13 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-nl.js: -------------------------------------------------------------------------------- 1 | /* Nederlands initialisation for the timepicker plugin */ 2 | /* Written by Lowie Hulzinga. */ 3 | jQuery(function($){ 4 | $.timepicker.regional['nl'] = { 5 | hourText: 'Uren', 6 | minuteText: 'Minuten', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Sluiten', 9 | nowButtonText: 'Actuele tijd', 10 | deselectButtonText: 'Wissen' } 11 | $.timepicker.setDefaults($.timepicker.regional['nl']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-pl.js: -------------------------------------------------------------------------------- 1 | /* Polish initialisation for the timepicker plugin */ 2 | /* Written by Mateusz Wadolkowski (mw@pcdoctor.pl). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['pl'] = { 5 | hourText: 'Godziny', 6 | minuteText: 'Minuty', 7 | amPmText: ['', ''], 8 | closeButtonText: 'Zamknij', 9 | nowButtonText: 'Teraz', 10 | deselectButtonText: 'Odznacz'} 11 | $.timepicker.setDefaults($.timepicker.regional['pl']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-pt-BR.js: -------------------------------------------------------------------------------- 1 | /* Brazilan initialisation for the timepicker plugin */ 2 | /* Written by Daniel Almeida (quantodaniel@gmail.com). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['pt-BR'] = { 5 | hourText: 'Hora', 6 | minuteText: 'Minuto', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Fechar', 9 | nowButtonText: 'Agora', 10 | deselectButtonText: 'Limpar' } 11 | $.timepicker.setDefaults($.timepicker.regional['pt-BR']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-ru.js: -------------------------------------------------------------------------------- 1 | /* Russian initialisation for the jQuery time picker plugin. */ 2 | /* Writen by Zakhar Day (zakhar.day@gmail.com) */ 3 | jQuery(function($){ 4 | $.timepicker.regional['ru'] = { 5 | hourText: 'Часы', 6 | minuteText: 'Минуты', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Готово', 9 | nowButtonText: 'Сейчас', 10 | deselectButtonText: 'Снять выделение' } 11 | $.timepicker.setDefaults($.timepicker.regional['ru']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-sl.js: -------------------------------------------------------------------------------- 1 | /* Slovenian localization for the jQuery time picker plugin. */ 2 | /* Written by Blaž Maležič (blaz@malezic.si) */ 3 | jQuery(function($){ 4 | $.timepicker.regional['sl'] = { 5 | hourText: 'Ure', 6 | minuteText: 'Minute', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Zapri', 9 | nowButtonText: 'Zdaj', 10 | deselectButtonText: 'Pobriši' } 11 | $.timepicker.setDefaults($.timepicker.regional['sl']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-sv.js: -------------------------------------------------------------------------------- 1 | /* Swedish initialisation for the timepicker plugin */ 2 | /* Written by Björn Westlin (bjorn.westlin@su.se). */ 3 | jQuery(function($){ 4 | $.timepicker.regional['sv'] = { 5 | hourText: 'Timme', 6 | minuteText: 'Minut', 7 | amPmText: ['AM', 'PM'] , 8 | closeButtonText: 'Stäng', 9 | nowButtonText: 'Nu', 10 | deselectButtonText: 'Rensa' } 11 | $.timepicker.setDefaults($.timepicker.regional['sv']); 12 | }); 13 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/i18n/jquery.ui.timepicker-tr.js: -------------------------------------------------------------------------------- 1 | /* Turkish initialisation for the jQuery time picker plugin. */ 2 | /* Written by Mutlu Tevfik Koçak (mtkocak@gmail.com) */ 3 | jQuery(function($){ 4 | $.timepicker.regional['tr'] = { 5 | hourText: 'Saat', 6 | minuteText: 'Dakika', 7 | amPmText: ['AM', 'PM'], 8 | closeButtonText: 'Kapat', 9 | nowButtonText: 'Şu anda', 10 | deselectButtonText: 'Seçimi temizle' } 11 | $.timepicker.setDefaults($.timepicker.regional['tr']); 12 | }); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/include/ui-1.10.0/jquery.ui.core.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.0 - 2013-01-24 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.core.js 4 | * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ 5 | (function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.10.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)}})})(jQuery); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/include/ui-1.10.0/jquery.ui.position.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.0 - 2013-01-24 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.position.js 4 | * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ 5 | (function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}function d(t){var n=t[0];return n.nodeType===9?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(n)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:n.preventDefault?{width:0,height:0,offset:{top:n.pageY,left:n.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("
"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};lr(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)10&&i<11,t.innerHTML="",n.removeChild(t)}()})(jQuery); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/include/ui-1.10.0/jquery.ui.tabs.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.0 - 2013-01-24 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.tabs.js 4 | * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ 5 | (function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&decodeURIComponent(e.href.replace(r,""))===decodeURIComponent(location.href.replace(r,""))}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.10.0",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),n.active=this._initialActive(),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(n.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_initialActive:function(){var t=this.options.active,n=this.options.collapsible,r=location.hash.substring(1);if(t===null){r&&this.tabs.each(function(n,i){if(e(i).attr("aria-controls")===r)return t=n,!1}),t===null&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(t===null||t===-1)t=this.tabs.length?0:!1}return t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),t===-1&&(t=n?!1:0)),!n&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r=this.element.parent();t==="fill"?(n=r.height(),n-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}})})(jQuery); -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/include/ui-1.10.0/jquery.ui.widget.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.0 - 2013-01-24 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.widget.js 4 | * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ 5 | (function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a={},f=t.split(".")[0];t=t.split(".")[1],i=f+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[f]=e[f]||{},s=e[f][t],o=e[f][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,r){if(!e.isFunction(r)){a[t]=r;return}a[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},i=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=i,s=r.apply(this,arguments),this._super=t,this._superApply=n,s}}()}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},a,{constructor:o,namespace:f,widgetName:t,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 |

Testing the timepicker within a jQuery Dialog

26 | 27 |
28 | 29 |

30 | The timepicker : 31 |
32 | 33 |

34 | 35 | 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /assets/vendor/jquery-timepicker/tests/jquery.ui.dialog.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Dialog 1.8.16 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Dialog 9 | * 10 | * Depends: 11 | * jquery.ui.core.js 12 | * jquery.ui.widget.js 13 | * jquery.ui.button.js 14 | * jquery.ui.draggable.js 15 | * jquery.ui.mouse.js 16 | * jquery.ui.position.js 17 | * jquery.ui.resizable.js 18 | */ 19 | (function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, 20 | position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ 21 | b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&!i.isDefaultPrevented()&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), 22 | h=c('
').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", 23 | e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); 24 | a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== 25 | b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; 26 | d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== 27 | f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, 28 | function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", 29 | handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, 30 | originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", 31 | f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): 32 | [a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); 33 | if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): 34 | e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= 35 | this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- 36 | b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.16",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), 37 | create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()
").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&& 39 | c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a" 6 | ], 7 | "description": "", 8 | "main": "", 9 | "moduleType": [], 10 | "license": "MIT", 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "devDependencies": { 19 | "jquery-timepicker": "*" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | *** WordPress Settings Framework Changelog *** 2 | 3 | version 1.6.11 4 | * [fix] PHP8 warning for usort callback 5 | 6 | 2018.10.25 - version 1.6.6 7 | * [Fixed] Ensure setting page capability is used for content block 8 | 9 | 2018.08.08 - version 1.6.6 10 | * [Update] Add ul element to checkbox lists 11 | * [Update] Update responsive styles 12 | 13 | 2016.04.14 - version 1.6.2 14 | * [Fixed] Undefined default error 15 | * [New] Repeatable groups 16 | 17 | 2014.07.08 - version 1.5.0 18 | * [New] Added "password" field 19 | * [New] Added "placeholder" attribute to text/password/textarea fields 20 | * [New] Added "wpsf_register_settings" filter 21 | * [Changed] No longer use the $wpsf_settings global 22 | * [Changed] wpsf_ functions now require an option group id 23 | 24 | 2012.10.09 - version 1.4.0 25 | * [New] Added wpsf_delete_settings() 26 | 27 | 2012.10.04 - version 1.3.0 28 | * [New] Added "custom" field 29 | * [Fixed] Color picker z-index issue 30 | 31 | 2012.10.01 - version 1.2.0 32 | * [New] Added an "editor" field 33 | 34 | 2012.08.27 - version 1.1.0 35 | * [New] Added "color" and "file" fields 36 | 37 | 2012.08.27 - version 1.0.0 38 | * Initial release 39 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iconicwp/wordpress-settings-framework", 3 | "authors": [ 4 | { 5 | "name": "Iconic", 6 | "email": "support@iconicwp.com" 7 | } 8 | ], 9 | "require-dev": { 10 | "woocommerce/woocommerce-sniffs": "^0.1.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "23a1c1d9ddcfd827f42dd13d029691d0", 8 | "packages": [ 9 | { 10 | "name": "dealerdirect/phpcodesniffer-composer-installer", 11 | "version": "v0.7.2", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", 15 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 20 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "composer-plugin-api": "^1.0 || ^2.0", 25 | "php": ">=5.3", 26 | "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" 27 | }, 28 | "require-dev": { 29 | "composer/composer": "*", 30 | "php-parallel-lint/php-parallel-lint": "^1.3.1", 31 | "phpcompatibility/php-compatibility": "^9.0" 32 | }, 33 | "type": "composer-plugin", 34 | "extra": { 35 | "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" 40 | } 41 | }, 42 | "notification-url": "https://packagist.org/downloads/", 43 | "license": [ 44 | "MIT" 45 | ], 46 | "authors": [ 47 | { 48 | "name": "Franck Nijhof", 49 | "email": "franck.nijhof@dealerdirect.com", 50 | "homepage": "http://www.frenck.nl", 51 | "role": "Developer / IT Manager" 52 | }, 53 | { 54 | "name": "Contributors", 55 | "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" 56 | } 57 | ], 58 | "description": "PHP_CodeSniffer Standards Composer Installer Plugin", 59 | "homepage": "http://www.dealerdirect.com", 60 | "keywords": [ 61 | "PHPCodeSniffer", 62 | "PHP_CodeSniffer", 63 | "code quality", 64 | "codesniffer", 65 | "composer", 66 | "installer", 67 | "phpcbf", 68 | "phpcs", 69 | "plugin", 70 | "qa", 71 | "quality", 72 | "standard", 73 | "standards", 74 | "style guide", 75 | "stylecheck", 76 | "tests" 77 | ], 78 | "support": { 79 | "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", 80 | "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" 81 | }, 82 | "time": "2022-02-04T12:51:07+00:00" 83 | }, 84 | { 85 | "name": "phpcompatibility/php-compatibility", 86 | "version": "9.3.5", 87 | "source": { 88 | "type": "git", 89 | "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", 90 | "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" 91 | }, 92 | "dist": { 93 | "type": "zip", 94 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", 95 | "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", 96 | "shasum": "" 97 | }, 98 | "require": { 99 | "php": ">=5.3", 100 | "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" 101 | }, 102 | "conflict": { 103 | "squizlabs/php_codesniffer": "2.6.2" 104 | }, 105 | "require-dev": { 106 | "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" 107 | }, 108 | "suggest": { 109 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", 110 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 111 | }, 112 | "type": "phpcodesniffer-standard", 113 | "notification-url": "https://packagist.org/downloads/", 114 | "license": [ 115 | "LGPL-3.0-or-later" 116 | ], 117 | "authors": [ 118 | { 119 | "name": "Wim Godden", 120 | "homepage": "https://github.com/wimg", 121 | "role": "lead" 122 | }, 123 | { 124 | "name": "Juliette Reinders Folmer", 125 | "homepage": "https://github.com/jrfnl", 126 | "role": "lead" 127 | }, 128 | { 129 | "name": "Contributors", 130 | "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" 131 | } 132 | ], 133 | "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", 134 | "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", 135 | "keywords": [ 136 | "compatibility", 137 | "phpcs", 138 | "standards" 139 | ], 140 | "support": { 141 | "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", 142 | "source": "https://github.com/PHPCompatibility/PHPCompatibility" 143 | }, 144 | "time": "2019-12-27T09:44:58+00:00" 145 | }, 146 | { 147 | "name": "phpcompatibility/phpcompatibility-paragonie", 148 | "version": "1.3.1", 149 | "source": { 150 | "type": "git", 151 | "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", 152 | "reference": "ddabec839cc003651f2ce695c938686d1086cf43" 153 | }, 154 | "dist": { 155 | "type": "zip", 156 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/ddabec839cc003651f2ce695c938686d1086cf43", 157 | "reference": "ddabec839cc003651f2ce695c938686d1086cf43", 158 | "shasum": "" 159 | }, 160 | "require": { 161 | "phpcompatibility/php-compatibility": "^9.0" 162 | }, 163 | "require-dev": { 164 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7", 165 | "paragonie/random_compat": "dev-master", 166 | "paragonie/sodium_compat": "dev-master" 167 | }, 168 | "suggest": { 169 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", 170 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 171 | }, 172 | "type": "phpcodesniffer-standard", 173 | "notification-url": "https://packagist.org/downloads/", 174 | "license": [ 175 | "LGPL-3.0-or-later" 176 | ], 177 | "authors": [ 178 | { 179 | "name": "Wim Godden", 180 | "role": "lead" 181 | }, 182 | { 183 | "name": "Juliette Reinders Folmer", 184 | "role": "lead" 185 | } 186 | ], 187 | "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", 188 | "homepage": "http://phpcompatibility.com/", 189 | "keywords": [ 190 | "compatibility", 191 | "paragonie", 192 | "phpcs", 193 | "polyfill", 194 | "standards" 195 | ], 196 | "support": { 197 | "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", 198 | "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" 199 | }, 200 | "time": "2021-02-15T10:24:51+00:00" 201 | }, 202 | { 203 | "name": "phpcompatibility/phpcompatibility-wp", 204 | "version": "2.1.3", 205 | "source": { 206 | "type": "git", 207 | "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", 208 | "reference": "d55de55f88697b9cdb94bccf04f14eb3b11cf308" 209 | }, 210 | "dist": { 211 | "type": "zip", 212 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/d55de55f88697b9cdb94bccf04f14eb3b11cf308", 213 | "reference": "d55de55f88697b9cdb94bccf04f14eb3b11cf308", 214 | "shasum": "" 215 | }, 216 | "require": { 217 | "phpcompatibility/php-compatibility": "^9.0", 218 | "phpcompatibility/phpcompatibility-paragonie": "^1.0" 219 | }, 220 | "require-dev": { 221 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7" 222 | }, 223 | "suggest": { 224 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", 225 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 226 | }, 227 | "type": "phpcodesniffer-standard", 228 | "notification-url": "https://packagist.org/downloads/", 229 | "license": [ 230 | "LGPL-3.0-or-later" 231 | ], 232 | "authors": [ 233 | { 234 | "name": "Wim Godden", 235 | "role": "lead" 236 | }, 237 | { 238 | "name": "Juliette Reinders Folmer", 239 | "role": "lead" 240 | } 241 | ], 242 | "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", 243 | "homepage": "http://phpcompatibility.com/", 244 | "keywords": [ 245 | "compatibility", 246 | "phpcs", 247 | "standards", 248 | "wordpress" 249 | ], 250 | "support": { 251 | "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", 252 | "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" 253 | }, 254 | "time": "2021-12-30T16:37:40+00:00" 255 | }, 256 | { 257 | "name": "squizlabs/php_codesniffer", 258 | "version": "3.7.1", 259 | "source": { 260 | "type": "git", 261 | "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 262 | "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" 263 | }, 264 | "dist": { 265 | "type": "zip", 266 | "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", 267 | "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", 268 | "shasum": "" 269 | }, 270 | "require": { 271 | "ext-simplexml": "*", 272 | "ext-tokenizer": "*", 273 | "ext-xmlwriter": "*", 274 | "php": ">=5.4.0" 275 | }, 276 | "require-dev": { 277 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 278 | }, 279 | "bin": [ 280 | "bin/phpcs", 281 | "bin/phpcbf" 282 | ], 283 | "type": "library", 284 | "extra": { 285 | "branch-alias": { 286 | "dev-master": "3.x-dev" 287 | } 288 | }, 289 | "notification-url": "https://packagist.org/downloads/", 290 | "license": [ 291 | "BSD-3-Clause" 292 | ], 293 | "authors": [ 294 | { 295 | "name": "Greg Sherwood", 296 | "role": "lead" 297 | } 298 | ], 299 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 300 | "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", 301 | "keywords": [ 302 | "phpcs", 303 | "standards" 304 | ], 305 | "support": { 306 | "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", 307 | "source": "https://github.com/squizlabs/PHP_CodeSniffer", 308 | "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" 309 | }, 310 | "time": "2022-06-18T07:21:10+00:00" 311 | }, 312 | { 313 | "name": "woocommerce/woocommerce-sniffs", 314 | "version": "0.1.3", 315 | "source": { 316 | "type": "git", 317 | "url": "https://github.com/woocommerce/woocommerce-sniffs.git", 318 | "reference": "4576d54595614d689bc4436acff8baaece3c5bb0" 319 | }, 320 | "dist": { 321 | "type": "zip", 322 | "url": "https://api.github.com/repos/woocommerce/woocommerce-sniffs/zipball/4576d54595614d689bc4436acff8baaece3c5bb0", 323 | "reference": "4576d54595614d689bc4436acff8baaece3c5bb0", 324 | "shasum": "" 325 | }, 326 | "require": { 327 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", 328 | "php": ">=7.0", 329 | "phpcompatibility/phpcompatibility-wp": "^2.1.0", 330 | "wp-coding-standards/wpcs": "^2.3.0" 331 | }, 332 | "type": "phpcodesniffer-standard", 333 | "notification-url": "https://packagist.org/downloads/", 334 | "license": [ 335 | "MIT" 336 | ], 337 | "authors": [ 338 | { 339 | "name": "Claudio Sanches", 340 | "email": "claudio@automattic.com" 341 | } 342 | ], 343 | "description": "WooCommerce sniffs", 344 | "keywords": [ 345 | "phpcs", 346 | "standards", 347 | "woocommerce", 348 | "wordpress" 349 | ], 350 | "support": { 351 | "issues": "https://github.com/woocommerce/woocommerce-sniffs/issues", 352 | "source": "https://github.com/woocommerce/woocommerce-sniffs/tree/0.1.3" 353 | }, 354 | "time": "2022-02-17T15:34:51+00:00" 355 | }, 356 | { 357 | "name": "wp-coding-standards/wpcs", 358 | "version": "2.3.0", 359 | "source": { 360 | "type": "git", 361 | "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", 362 | "reference": "7da1894633f168fe244afc6de00d141f27517b62" 363 | }, 364 | "dist": { 365 | "type": "zip", 366 | "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", 367 | "reference": "7da1894633f168fe244afc6de00d141f27517b62", 368 | "shasum": "" 369 | }, 370 | "require": { 371 | "php": ">=5.4", 372 | "squizlabs/php_codesniffer": "^3.3.1" 373 | }, 374 | "require-dev": { 375 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", 376 | "phpcompatibility/php-compatibility": "^9.0", 377 | "phpcsstandards/phpcsdevtools": "^1.0", 378 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 379 | }, 380 | "suggest": { 381 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." 382 | }, 383 | "type": "phpcodesniffer-standard", 384 | "notification-url": "https://packagist.org/downloads/", 385 | "license": [ 386 | "MIT" 387 | ], 388 | "authors": [ 389 | { 390 | "name": "Contributors", 391 | "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" 392 | } 393 | ], 394 | "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", 395 | "keywords": [ 396 | "phpcs", 397 | "standards", 398 | "wordpress" 399 | ], 400 | "support": { 401 | "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", 402 | "source": "https://github.com/WordPress/WordPress-Coding-Standards", 403 | "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" 404 | }, 405 | "time": "2020-05-13T23:57:56+00:00" 406 | } 407 | ], 408 | "packages-dev": [], 409 | "aliases": [], 410 | "minimum-stability": "stable", 411 | "stability-flags": [], 412 | "prefer-stable": false, 413 | "prefer-lowest": false, 414 | "platform": [], 415 | "platform-dev": [], 416 | "plugin-api-version": "2.1.0" 417 | } 418 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Generally-applicable sniffs for WooCommerce plugins 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | */dev-lib/* 24 | */node_modules/* 25 | */vendor/* 26 | .github/ 27 | 28 | -------------------------------------------------------------------------------- /settings/example-settings.php: -------------------------------------------------------------------------------- 1 | 'general', 33 | 'section_title' => 'General Settings', 34 | 'section_description' => 'Some intro description about this section.', 35 | 'section_order' => 5, 36 | 'fields' => array( 37 | array( 38 | 'id' => 'text', 39 | 'title' => 'Text', 40 | 'desc' => 'This is a description.', 41 | 'placeholder' => 'This is a placeholder.', 42 | 'type' => 'text', 43 | 'default' => 'This is default', 44 | ), 45 | array( 46 | 'id' => 'number', 47 | 'title' => 'Number', 48 | 'desc' => 'This is a description.', 49 | 'type' => 'number', 50 | 'default' => 10, 51 | ), 52 | array( 53 | 'id' => 'time', 54 | 'title' => 'Time Picker', 55 | 'desc' => 'This is a description.', 56 | 'type' => 'time', 57 | 'timepicker' => array(), // Array of timepicker options (http://fgelinas.com/code/timepicker). 58 | ), 59 | array( 60 | 'id' => 'date', 61 | 'title' => 'Date Picker', 62 | 'desc' => 'This is a description.', 63 | 'type' => 'date', 64 | 'datepicker' => array(), // Array of datepicker options (http://api.jqueryui.com/datepicker/). 65 | ), 66 | array( 67 | 'id' => 'image_radio', 68 | 'title' => 'Select a radio', 69 | 'desc' => 'This is a description.', 70 | 'type' => 'image_radio', 71 | 'choices' => array( 72 | 'choice-1' => array( 73 | 'text' => 'Choice 1', 74 | 'image' => 'https://picsum.photos/100', 75 | ), 76 | 'choice-2' => array( 77 | 'text' => 'Choice 2', 78 | 'image' => 'https://picsum.photos/100', 79 | ), 80 | ), 81 | ), 82 | array( 83 | 'id' => 'image_checkboxes', 84 | 'title' => 'Select a Checkbox', 85 | 'desc' => 'This is a description.', 86 | 'type' => 'image_checkboxes', 87 | 'choices' => array( 88 | 'choice-1' => array( 89 | 'text' => 'Choice 1', 90 | 'image' => 'https://picsum.photos/100', 91 | ), 92 | 'choice-2' => array( 93 | 'text' => 'Choice 2', 94 | 'image' => 'https://picsum.photos/100', 95 | ), 96 | 'choice-2' => array( 97 | 'text' => 'Choice 3', 98 | 'image' => 'https://picsum.photos/100', 99 | ), 100 | ), 101 | ), 102 | array( 103 | 'id' => 'group', 104 | 'title' => 'Group', 105 | 'desc' => 'This is a description.', 106 | 'type' => 'group', 107 | 'subfields' => array( 108 | // accepts most types of fields. 109 | array( 110 | 'id' => 'sub-text', 111 | 'title' => 'Sub Text', 112 | 'desc' => 'This is a description.', 113 | 'placeholder' => 'This is a placeholder.', 114 | 'type' => 'text', 115 | 'default' => 'Sub text', 116 | ), 117 | ), 118 | ), 119 | array( 120 | 'id' => 'password', 121 | 'title' => 'Password', 122 | 'desc' => 'This is a description.', 123 | 'placeholder' => 'This is a placeholder.', 124 | 'type' => 'password', 125 | 'default' => 'Example', 126 | ), 127 | array( 128 | 'id' => 'textarea', 129 | 'title' => 'Textarea', 130 | 'desc' => 'This is a description.', 131 | 'placeholder' => 'This is a placeholder.', 132 | 'type' => 'textarea', 133 | 'default' => 'This is default', 134 | ), 135 | array( 136 | 'id' => 'select', 137 | 'title' => 'Select', 138 | 'desc' => 'This is a description.', 139 | 'conditional_desc' => array( 140 | 'red' => 'Description for value: red', 141 | 'green' => 'Description for value: green', 142 | 'blue' => 'Description for value: blue', 143 | ), 144 | 'type' => 'select', 145 | 'default' => 'green', 146 | 'multiple' => false, // Can be 'true'. 147 | 'choices' => array( 148 | 'red' => 'Red', 149 | 'green' => 'Green', 150 | 'blue' => 'Blue', 151 | ), 152 | ), 153 | array( 154 | 'id' => 'radio', 155 | 'title' => 'Radio', 156 | 'desc' => 'This is a description.', 157 | 'type' => 'radio', 158 | 'default' => 'green', 159 | 'choices' => array( 160 | 'red' => 'Red', 161 | 'green' => 'Green', 162 | 'blue' => 'Blue', 163 | ), 164 | ), 165 | array( 166 | 'id' => 'checkbox', 167 | 'title' => 'Checkbox', 168 | 'desc' => 'This is a description.', 169 | 'type' => 'checkbox', 170 | 'default' => 1, 171 | ), 172 | array( 173 | 'id' => 'checkboxes', 174 | 'title' => 'Checkboxes', 175 | 'desc' => 'This is a description.', 176 | 'type' => 'checkboxes', 177 | 'default' => array( 178 | 'red', 179 | 'blue', 180 | ), 181 | 'choices' => array( 182 | 'red' => 'Red', 183 | 'green' => 'Green', 184 | 'blue' => 'Blue', 185 | ), 186 | ), 187 | array( 188 | 'id' => 'color', 189 | 'title' => 'Color', 190 | 'desc' => 'This is a description.', 191 | 'type' => 'color', 192 | 'default' => '#ffffff', 193 | ), 194 | array( 195 | 'id' => 'file', 196 | 'title' => 'File', 197 | 'desc' => 'This is a description.', 198 | 'type' => 'file', 199 | 'default' => '', 200 | ), 201 | array( 202 | 'id' => 'editor', 203 | 'title' => 'Editor', 204 | 'desc' => 'This is a description.', 205 | 'type' => 'editor', 206 | 'default' => '', 207 | 'editor_settings' => array( 208 | 'teeny' => false, 209 | ), 210 | ), 211 | array( 212 | 'id' => 'code_editor', 213 | 'title' => 'Code Editor', 214 | 'desc' => 'This is a description.', 215 | 'placeholder' => 'This is a placeholder.', 216 | 'type' => 'code_editor', 217 | 'mimetype' => 'css', 218 | 'default' => 'This is default.', 219 | ), 220 | array( 221 | 'id' => 'export', 222 | 'title' => 'Export settings', 223 | 'subtitle' => 'Export settings.', 224 | 'type' => 'export', 225 | ), 226 | array( 227 | 'id' => 'import', 228 | 'title' => 'Import Settings', 229 | 'subtitle' => 'Import settings.', 230 | 'type' => 'import', 231 | ), 232 | ), 233 | ); 234 | 235 | // More Settings section. 236 | $wpsf_settings[] = array( 237 | 'section_id' => 'more', 238 | 'section_title' => 'More Settings', 239 | 'section_order' => 10, 240 | 'fields' => array( 241 | array( 242 | 'id' => 'heading-tooltip-link', 243 | 'title' => 'Heading with tooltip', 244 | 'subtitle' => 'Lorem ipsum dolor sit amet congue aliqua scelerisque dictumst ornare nullam suspendisse.', 245 | 'desc' => 'This is a description.', 246 | 'type' => 'text', 247 | 'default' => 'This is default', 248 | 'link' => array( 249 | 'url' => esc_url( 'https://google.com' ), 250 | 'type' => 'tooltip', // Can be 'tooltip' or 'link'. Default is 'tooltip'. 251 | 'text' => 'Learn More', // Default is 'Learn More'. 252 | 'external' => true, // Default is `true`. 253 | ), 254 | ), 255 | array( 256 | 'id' => 'heading-subtitle-link', 257 | 'title' => 'Heading with link', 258 | 'subtitle' => 'Lorem ipsum dolor sit amet congue aliqua scelerisque dictumst ornare nullam suspendisse.', 259 | 'desc' => 'This is a description.', 260 | 'type' => 'text', 261 | 'default' => 'This is default', 262 | 'link' => array( 263 | 'url' => esc_url( 'https://google.com' ), 264 | 'type' => 'link', // Can be 'tooltip' or 'link'. Default is 'tooltip'. 265 | 'text' => 'Learn More', // Default is 'Learn More'. 266 | 'external' => true, // Default is `true`. 267 | ), 268 | ), 269 | array( 270 | 'id' => 'more-text', 271 | 'title' => 'More Text', 272 | 'desc' => 'This is a description.', 273 | 'type' => 'text', 274 | 'default' => 'This is default', 275 | ), 276 | array( 277 | 'id' => 'control-group', 278 | 'title' => 'Control Group', 279 | 'subtitle' => 'Select option 1 or 2 to show and hide controls.', 280 | 'type' => 'select', 281 | 'choices' => array( 282 | 'option-1' => 'Option 1', 283 | 'option-2' => 'Option 2', 284 | 'option-3' => 'Option 3', 285 | ), 286 | 'default' => 'text', 287 | ), 288 | array( 289 | 'id' => 'show-if-option-1', 290 | 'title' => 'Show if Option 1', 291 | 'subtitle' => 'Will show if Option 1 is set.', 292 | 'type' => 'select', 293 | 'type' => 'text', 294 | 'default' => 'This is default', 295 | 'show_if' => array( // Field will only show, if the control `more_control-group` is set to Option 1. 296 | array( 297 | 'field' => 'more_control-group', 298 | 'value' => array( 'option-1' ), 299 | ), 300 | ), 301 | ), 302 | array( 303 | 'id' => 'show-if-option-2', 304 | 'title' => 'Show if Option 2', 305 | 'subtitle' => 'Will show if Option 2 is set.', 306 | 'type' => 'select', 307 | 'type' => 'text', 308 | 'default' => 'This is default', 309 | 'show_if' => array( // Field will only show, if the control `more_control-group` is set to Option 2. 310 | array( 311 | 'field' => 'more_control-group', 312 | 'value' => array( 'option-2' ), 313 | ), 314 | ), 315 | ), 316 | array( 317 | 'id' => 'show-if-option-2-or-3', 318 | 'title' => 'Show if Option 2 or 3', 319 | 'subtitle' => 'Will show if Option 2 or 3 is set.', 320 | 'type' => 'select', 321 | 'type' => 'text', 322 | 'default' => 'This is default', 323 | 'show_if' => array( // Field will only show, if the control `more_control-group` is set to Option 2 or Option 3. 324 | array( 325 | 'field' => 'more_control-group', 326 | 'value' => array( 'option-2', 'option-3' ), 327 | ), 328 | ), 329 | ), 330 | array( 331 | 'id' => 'hide-if-option-1', 332 | 'title' => 'Hide if Option 1', 333 | 'subtitle' => 'Will hide if Option 1 is set.', 334 | 'type' => 'select', 335 | 'type' => 'text', 336 | 'default' => 'This is default', 337 | 'hide_if' => array( // Field will only hide, if the control `more_control-group` is set to Option 1. 338 | array( 339 | 'field' => 'more_control-group', 340 | 'value' => array( 'option-1' ), 341 | ), 342 | ), 343 | ), 344 | array( 345 | 'id' => 'section-control', 346 | 'title' => 'Will show Additional Settings Group if toggled', 347 | 'flux-checkout', 348 | 'type' => 'toggle', 349 | 'default' => false, 350 | ), 351 | ), 352 | ); 353 | 354 | $wpsf_settings[] = array( 355 | 'section_id' => 'additional', 356 | 'section_title' => 'Additional Settings', 357 | 'section_order' => 10, 358 | 'section_control_group' => 'section-control', 359 | 'show_if' => array( // Field will only show, if the control `more_section-control` is set to true. 360 | array( 361 | 'field' => 'more_section-control', 362 | 'value' => array( '1' ), 363 | ), 364 | ), 365 | 'fields' => array( 366 | array( 367 | 'id' => 'additional-text', 368 | 'title' => 'Additional Text', 369 | 'desc' => 'This is a description.', 370 | 'type' => 'text', 371 | 'default' => 'This is default', 372 | ), 373 | array( 374 | 'id' => 'additional-number', 375 | 'title' => 'Additional Number', 376 | 'desc' => 'This is a description.', 377 | 'type' => 'number', 378 | 'default' => 10, 379 | ), 380 | ), 381 | ); 382 | 383 | return $wpsf_settings; 384 | } 385 | 386 | /** 387 | * Tabbed example. 388 | * 389 | * @param array $wpsf_settings settings. 390 | */ 391 | function wpsf_tabbed_settings( $wpsf_settings ) { 392 | // Tabs. 393 | $wpsf_settings['tabs'] = array( 394 | array( 395 | 'id' => 'tab_1', 396 | 'title' => esc_html__( 'Tab 1', 'text-domain' ), 397 | ), 398 | array( 399 | 'id' => 'tab_2', 400 | 'title' => esc_html__( 'Tab 2', 'text-domain' ), 401 | ), 402 | array( 403 | 'id' => 'tab_3', 404 | 'title' => esc_html__( 'Tab 3', 'text-domain' ), 405 | 'tab_control_group' => 'tab-control', 406 | 'show_if' => array( // Field will only show if the control `tab_2_section_2_tab-control` is set to true. 407 | array( 408 | 'field' => 'tab_2_section_3_tab-control', 409 | 'value' => array( '1' ), 410 | ), 411 | ), 412 | ), 413 | ); 414 | 415 | // Settings. 416 | $wpsf_settings['sections'] = array( 417 | array( 418 | 'tab_id' => 'tab_1', 419 | 'section_id' => 'section_1', 420 | 'section_title' => 'Section 1', 421 | 'section_order' => 10, 422 | 'fields' => array( 423 | array( 424 | 'id' => 'text-1', 425 | 'title' => 'Text', 426 | 'desc' => 'This is a description.', 427 | 'type' => 'text', 428 | 'default' => 'This is default', 429 | ), 430 | ), 431 | ), 432 | array( 433 | 'tab_id' => 'tab_1', 434 | 'section_id' => 'section_2', 435 | 'section_title' => 'Section 2', 436 | 'section_order' => 10, 437 | 'fields' => array( 438 | array( 439 | 'id' => 'text-2', 440 | 'title' => 'Text', 441 | // Format of href is #tab-id|field-id. You can choose to skip the field id. 442 | 'desc' => 'This is a description. This is a link to a setting in a different tab.', 443 | 'type' => 'text', 444 | 'default' => 'This is default', 445 | ), 446 | ), 447 | ), 448 | array( 449 | 'tab_id' => 'tab_2', 450 | 'section_id' => 'section_3', 451 | 'section_title' => 'Section 3', 452 | 'section_order' => 10, 453 | 'fields' => array( 454 | array( 455 | 'id' => 'text-3', 456 | 'title' => 'Text', 457 | 'desc' => 'This is a description.', 458 | 'type' => 'text', 459 | 'default' => 'This is default', 460 | ), 461 | array( 462 | 'id' => 'tab-control', 463 | 'title' => 'Will show Tab 3 if toggled', 464 | 'type' => 'toggle', 465 | 'default' => false, 466 | ), 467 | ), 468 | ), 469 | array( 470 | 'tab_id' => 'tab_3', 471 | 'section_id' => 'section_4', 472 | 'section_title' => 'Section 4', 473 | 'section_order' => 10, 474 | 'fields' => array( 475 | array( 476 | 'id' => 'text-4', 477 | 'title' => 'Text', 478 | 'desc' => 'This is a description.', 479 | 'type' => 'text', 480 | 'default' => 'This is default', 481 | ), 482 | array( 483 | 'id' => 'complex-group-1', 484 | 'title' => 'Complex Show Hide 1', 485 | 'subtitle' => 'Multiple controls can show or hide fields', 486 | 'type' => 'select', 487 | 'choices' => array( 488 | 'option-1' => 'Option 1', 489 | 'option-2' => 'Option 2', 490 | 'option-3' => 'Option 3', 491 | ), 492 | 'default' => 'text', 493 | ), 494 | array( 495 | 'id' => 'complex-group-2', 496 | 'title' => 'Complex Show Hide 2', 497 | 'subtitle' => 'Multiple controls can show or hide fields', 498 | 'type' => 'toggle', 499 | 'default' => false, 500 | ), 501 | array( 502 | 'id' => 'complex-group-3', 503 | 'title' => 'Complex Show Hide 3', 504 | 'subtitle' => 'Multiple controls can show or hide fields', 505 | 'type' => 'toggle', 506 | 'default' => false, 507 | ), 508 | array( 509 | 'id' => 'complex-group-show', 510 | 'title' => 'Complex Show Example', 511 | 'subtitle' => 'Will show if Control 1 is Option 1 or Option 2 AND Control 2 is True, OR if Control 3 is true', 512 | 'type' => 'select', 513 | 'type' => 'text', 514 | 'default' => 'This is default', 515 | 'show_if' => array( 516 | // An array here is an AND group. 517 | array( 518 | // Show if Control 1 is Option 1 OR Option 2. 519 | array( 520 | 'field' => 'tab_3_section_4_complex-group-1', 521 | 'value' => array( 'option-1', 'option-2' ), 522 | ), 523 | // AND Control 2 is True. 524 | array( 525 | 'field' => 'tab_3_section_4_complex-group-2', 526 | 'value' => array( '1' ), 527 | ), 528 | ), 529 | // OR show if Control 3 is True. 530 | array( 531 | 'field' => 'tab_3_section_4_complex-group-3', 532 | 'value' => array( '1' ), 533 | ), 534 | ), 535 | ), 536 | array( 537 | 'id' => 'complex-group-hide', 538 | 'title' => 'Complex Hide Example', 539 | 'subtitle' => 'Will hide if Control 1 is Option 1 or Option 2 AND Control 2 is True, OR if Control 3 is true', 540 | 'type' => 'select', 541 | 'type' => 'text', 542 | 'default' => 'This is default', 543 | 'hide_if' => array( 544 | // An array here is an AND group. 545 | array( 546 | // Hide if Control 1 is Option 1 OR Option 2. 547 | array( 548 | 'field' => 'tab_3_section_4_complex-group-1', 549 | 'value' => array( 'option-1', 'option-2' ), 550 | ), 551 | // AND Control 2 is True. 552 | array( 553 | 'field' => 'tab_3_section_4_complex-group-2', 554 | 'value' => array( '1' ), 555 | ), 556 | ), 557 | // OR hide if Control 3 is True. 558 | array( 559 | 'field' => 'tab_3_section_4_complex-group-3', 560 | 'value' => array( '1' ), 561 | ), 562 | ), 563 | ), 564 | ), 565 | ), 566 | ); 567 | 568 | return $wpsf_settings; 569 | } 570 | -------------------------------------------------------------------------------- /wpsf-test.php: -------------------------------------------------------------------------------- 1 | plugin_path = plugin_dir_path( __FILE__ ); 35 | 36 | // Include and create a new WordPressSettingsFramework. 37 | require_once $this->plugin_path . 'wp-settings-framework.php'; 38 | $this->wpsf = new WordPressSettingsFramework( $this->plugin_path . 'settings/example-settings.php', 'my_example_settings' ); 39 | 40 | // Add admin menu. 41 | add_action( 'admin_menu', array( $this, 'add_settings_page' ), 20 ); 42 | 43 | // Add an optional settings validation filter (recommended). 44 | add_filter( $this->wpsf->get_option_group() . '_settings_validate', array( &$this, 'validate_settings' ) ); 45 | } 46 | 47 | /** 48 | * Add settings page. 49 | */ 50 | public function add_settings_page() { 51 | $this->wpsf->add_settings_page( 52 | array( 53 | 'parent_slug' => 'woocommerce', 54 | 'page_title' => esc_html__( 'Page Title', 'text-domain' ), 55 | 'menu_title' => esc_html__( 'menu Title', 'text-domain' ), 56 | 'capability' => 'manage_woocommerce', 57 | ) 58 | ); 59 | } 60 | 61 | /** 62 | * Validate settings. 63 | * 64 | * @param mixed $input Input data. 65 | * 66 | * @return mixed $input 67 | */ 68 | public function validate_settings( $input ) { 69 | // Do your settings validation here 70 | // Same as $sanitize_callback from http://codex.wordpress.org/Function_Reference/register_setting. 71 | return $input; 72 | } 73 | } 74 | 75 | $wpsf_test = new WPSFTest(); 76 | --------------------------------------------------------------------------------