| Total Complexity | 575 |
| Complexity/F | 2.34 |
| Lines of Code | 3605 |
| Function Count | 246 |
| Duplicated Lines | 1240 |
| Ratio | 34.4 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like controls/js/script.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | /* jshint -W079 */ |
||
| 3 | View Code Duplication | if ( _.isUndefined( window.kirkiSetSettingValue ) ) { |
|
|
|
|||
| 4 | var kirkiSetSettingValue = { // jscs:ignore requireVarDeclFirst |
||
| 5 | |||
| 6 | /** |
||
| 7 | * Set the value of the control. |
||
| 8 | * |
||
| 9 | * @since 3.0.0 |
||
| 10 | * @param string setting The setting-ID. |
||
| 11 | * @param mixed value The value. |
||
| 12 | */ |
||
| 13 | set: function( setting, value ) { |
||
| 14 | |||
| 15 | /** |
||
| 16 | * Get the control of the sub-setting. |
||
| 17 | * This will be used to get properties we need from that control, |
||
| 18 | * and determine if we need to do any further work based on those. |
||
| 19 | */ |
||
| 20 | var $this = this, |
||
| 21 | subControl = wp.customize.settings.controls[ setting ], |
||
| 22 | valueJSON; |
||
| 23 | |||
| 24 | // If the control doesn't exist then return. |
||
| 25 | if ( _.isUndefined( subControl ) ) { |
||
| 26 | return true; |
||
| 27 | } |
||
| 28 | |||
| 29 | // First set the value in the wp object. The control type doesn't matter here. |
||
| 30 | $this.setValue( setting, value ); |
||
| 31 | |||
| 32 | // Process visually changing the value based on the control type. |
||
| 33 | switch ( subControl.type ) { |
||
| 34 | |||
| 35 | case 'kirki-background': |
||
| 36 | if ( ! _.isUndefined( value['background-color'] ) ) { |
||
| 37 | $this.setColorPicker( $this.findElement( setting, '.kirki-color-control' ), value['background-color'] ); |
||
| 38 | } |
||
| 39 | $this.findElement( setting, '.placeholder, .thumbnail' ).removeClass().addClass( 'placeholder' ).html( 'No file selected' ); |
||
| 40 | _.each( ['background-repeat', 'background-position'], function( subVal ) { |
||
| 41 | if ( ! _.isUndefined( value[ subVal ] ) ) { |
||
| 42 | $this.setSelectWoo( $this.findElement( setting, '.' + subVal + ' select' ), value[ subVal ] ); |
||
| 43 | } |
||
| 44 | }); |
||
| 45 | _.each( ['background-size', 'background-attachment'], function( subVal ) { |
||
| 46 | jQuery( $this.findElement( setting, '.' + subVal + ' input[value="' + value + '"]' ) ).prop( 'checked', true ); |
||
| 47 | }); |
||
| 48 | valueJSON = JSON.stringify( value ).replace( /'/g, ''' ); |
||
| 49 | jQuery( $this.findElement( setting, '.background-hidden-value' ).attr( 'value', valueJSON ) ).trigger( 'change' ); |
||
| 50 | break; |
||
| 51 | |||
| 52 | case 'kirki-code': |
||
| 53 | jQuery( $this.findElement( setting, '.CodeMirror' ) )[0].CodeMirror.setValue( value ); |
||
| 54 | break; |
||
| 55 | |||
| 56 | case 'checkbox': |
||
| 57 | case 'kirki-switch': |
||
| 58 | case 'kirki-toggle': |
||
| 59 | value = ( 1 === value || '1' === value || true === value ) ? true : false; |
||
| 60 | jQuery( $this.findElement( setting, 'input' ) ).prop( 'checked', value ); |
||
| 61 | wp.customize.instance( setting ).set( value ); |
||
| 62 | break; |
||
| 63 | |||
| 64 | case 'kirki-select': |
||
| 65 | case 'kirki-preset': |
||
| 66 | case 'kirki-fontawesome': |
||
| 67 | $this.setSelectWoo( $this.findElement( setting, 'select' ), value ); |
||
| 68 | break; |
||
| 69 | |||
| 70 | case 'kirki-slider': |
||
| 71 | jQuery( $this.findElement( setting, 'input' ) ).prop( 'value', value ); |
||
| 72 | jQuery( $this.findElement( setting, '.kirki_range_value .value' ) ).html( value ); |
||
| 73 | break; |
||
| 74 | |||
| 75 | case 'kirki-generic': |
||
| 76 | if ( _.isUndefined( subControl.choices ) || _.isUndefined( subControl.choices.element ) ) { |
||
| 77 | subControl.choices.element = 'input'; |
||
| 78 | } |
||
| 79 | jQuery( $this.findElement( setting, subControl.choices.element ) ).prop( 'value', value ); |
||
| 80 | break; |
||
| 81 | |||
| 82 | case 'kirki-color': |
||
| 83 | $this.setColorPicker( $this.findElement( setting, '.kirki-color-control' ), value ); |
||
| 84 | break; |
||
| 85 | |||
| 86 | case 'kirki-multicheck': |
||
| 87 | $this.findElement( setting, 'input' ).each( function() { |
||
| 88 | jQuery( this ).prop( 'checked', false ); |
||
| 89 | }); |
||
| 90 | _.each( value, function( subValue, i ) { |
||
| 91 | jQuery( $this.findElement( setting, 'input[value="' + value[ i ] + '"]' ) ).prop( 'checked', true ); |
||
| 92 | }); |
||
| 93 | break; |
||
| 94 | |||
| 95 | case 'kirki-multicolor': |
||
| 96 | _.each( value, function( subVal, index ) { |
||
| 97 | $this.setColorPicker( $this.findElement( setting, '.multicolor-index-' + index ), subVal ); |
||
| 98 | }); |
||
| 99 | break; |
||
| 100 | |||
| 101 | case 'kirki-radio-buttonset': |
||
| 102 | case 'kirki-radio-image': |
||
| 103 | case 'kirki-radio': |
||
| 104 | case 'kirki-dashicons': |
||
| 105 | case 'kirki-color-palette': |
||
| 106 | case 'kirki-palette': |
||
| 107 | jQuery( $this.findElement( setting, 'input[value="' + value + '"]' ) ).prop( 'checked', true ); |
||
| 108 | break; |
||
| 109 | |||
| 110 | case 'kirki-typography': |
||
| 111 | _.each( ['font-family', 'variant', 'subsets'], function( subVal ) { |
||
| 112 | if ( ! _.isUndefined( value[ subVal ] ) ) { |
||
| 113 | $this.setSelectWoo( $this.findElement( setting, '.' + subVal + ' select' ), value[ subVal ] ); |
||
| 114 | } |
||
| 115 | }); |
||
| 116 | _.each( ['font-size', 'line-height', 'letter-spacing', 'word-spacing'], function( subVal ) { |
||
| 117 | if ( ! _.isUndefined( value[ subVal ] ) ) { |
||
| 118 | jQuery( $this.findElement( setting, '.' + subVal + ' input' ) ).prop( 'value', value[ subVal ] ); |
||
| 119 | } |
||
| 120 | }); |
||
| 121 | |||
| 122 | if ( ! _.isUndefined( value.color ) ) { |
||
| 123 | $this.setColorPicker( $this.findElement( setting, '.kirki-color-control' ), value.color ); |
||
| 124 | } |
||
| 125 | valueJSON = JSON.stringify( value ).replace( /'/g, ''' ); |
||
| 126 | jQuery( $this.findElement( setting, '.typography-hidden-value' ).attr( 'value', valueJSON ) ).trigger( 'change' ); |
||
| 127 | break; |
||
| 128 | |||
| 129 | case 'kirki-dimensions': |
||
| 130 | _.each( value, function( subValue, id ) { |
||
| 131 | jQuery( $this.findElement( setting, '.' + id + ' input' ) ).prop( 'value', subValue ); |
||
| 132 | }); |
||
| 133 | break; |
||
| 134 | |||
| 135 | case 'kirki-repeater': |
||
| 136 | |||
| 137 | // Not yet implemented. |
||
| 138 | break; |
||
| 139 | |||
| 140 | case 'kirki-custom': |
||
| 141 | |||
| 142 | // Do nothing. |
||
| 143 | break; |
||
| 144 | default: |
||
| 145 | jQuery( $this.findElement( setting, 'input' ) ).prop( 'value', value ); |
||
| 146 | } |
||
| 147 | }, |
||
| 148 | |||
| 149 | /** |
||
| 150 | * Set the value for colorpickers. |
||
| 151 | * CAUTION: This only sets the value visually, it does not change it in th wp object. |
||
| 152 | * |
||
| 153 | * @since 3.0.0 |
||
| 154 | * @param object selector jQuery object for this element. |
||
| 155 | * @param string value The value we want to set. |
||
| 156 | */ |
||
| 157 | setColorPicker: function( selector, value ) { |
||
| 158 | selector.attr( 'data-default-color', value ).data( 'default-color', value ).wpColorPicker( 'color', value ); |
||
| 159 | }, |
||
| 160 | |||
| 161 | /** |
||
| 162 | * Sets the value in a selectWoo element. |
||
| 163 | * CAUTION: This only sets the value visually, it does not change it in th wp object. |
||
| 164 | * |
||
| 165 | * @since 3.0.0 |
||
| 166 | * @param string selector The CSS identifier for this selectWoo. |
||
| 167 | * @param string value The value we want to set. |
||
| 168 | */ |
||
| 169 | setSelectWoo: function( selector, value ) { |
||
| 170 | jQuery( selector ).selectWoo().val( value ).trigger( 'change' ); |
||
| 171 | }, |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Sets the value in textarea elements. |
||
| 175 | * CAUTION: This only sets the value visually, it does not change it in th wp object. |
||
| 176 | * |
||
| 177 | * @since 3.0.0 |
||
| 178 | * @param string selector The CSS identifier for this textarea. |
||
| 179 | * @param string value The value we want to set. |
||
| 180 | */ |
||
| 181 | setTextarea: function( selector, value ) { |
||
| 182 | jQuery( selector ).prop( 'value', value ); |
||
| 183 | }, |
||
| 184 | |||
| 185 | /** |
||
| 186 | * Finds an element inside this control. |
||
| 187 | * |
||
| 188 | * @since 3.0.0 |
||
| 189 | * @param string setting The setting ID. |
||
| 190 | * @param string element The CSS identifier. |
||
| 191 | */ |
||
| 192 | findElement: function( setting, element ) { |
||
| 193 | return wp.customize.control( setting ).container.find( element ); |
||
| 194 | }, |
||
| 195 | |||
| 196 | /** |
||
| 197 | * Updates the value in the wp.customize object. |
||
| 198 | * |
||
| 199 | * @since 3.0.0 |
||
| 200 | * @param string setting The setting-ID. |
||
| 201 | * @param mixed value The value. |
||
| 202 | */ |
||
| 203 | setValue: function( setting, value, timeout ) { |
||
| 204 | timeout = ( _.isUndefined( timeout ) ) ? 100 : parseInt( timeout, 10 ); |
||
| 205 | wp.customize.instance( setting ).set({}); |
||
| 206 | setTimeout( function() { |
||
| 207 | wp.customize.instance( setting ).set( value ); |
||
| 208 | }, timeout ); |
||
| 209 | } |
||
| 210 | }; |
||
| 211 | } |
||
| 212 | var kirki = { |
||
| 213 | |||
| 214 | initialized: false, |
||
| 215 | |||
| 216 | /** |
||
| 217 | * Initialize the object. |
||
| 218 | * |
||
| 219 | * @since 3.0.17 |
||
| 220 | * @returns {null} |
||
| 221 | */ |
||
| 222 | initialize: function() { |
||
| 223 | var self = this; |
||
| 224 | |||
| 225 | // We only need to initialize once. |
||
| 226 | if ( self.initialized ) { |
||
| 227 | return; |
||
| 228 | } |
||
| 229 | |||
| 230 | setTimeout( function() { |
||
| 231 | kirki.util.webfonts.standard.initialize(); |
||
| 232 | kirki.util.webfonts.google.initialize(); |
||
| 233 | }, 150 ); |
||
| 234 | |||
| 235 | // Mark as initialized. |
||
| 236 | self.initialized = true; |
||
| 237 | } |
||
| 238 | }; |
||
| 239 | |||
| 240 | // Initialize the kirki object. |
||
| 241 | kirki.initialize(); |
||
| 242 | var kirki = kirki || {}; |
||
| 243 | kirki = jQuery.extend( kirki, { |
||
| 244 | |||
| 245 | /** |
||
| 246 | * An object containing definitions for controls. |
||
| 247 | * |
||
| 248 | * @since 3.0.16 |
||
| 249 | */ |
||
| 250 | control: { |
||
| 251 | |||
| 252 | /** |
||
| 253 | * The radio control. |
||
| 254 | * |
||
| 255 | * @since 3.0.17 |
||
| 256 | */ |
||
| 257 | 'kirki-radio': { |
||
| 258 | |||
| 259 | /** |
||
| 260 | * Init the control. |
||
| 261 | * |
||
| 262 | * @since 3.0.17 |
||
| 263 | * @param {Object} control - The customizer control object. |
||
| 264 | * @returns {null} |
||
| 265 | */ |
||
| 266 | init: function( control ) { |
||
| 267 | var self = this; |
||
| 268 | |||
| 269 | // Render the template. |
||
| 270 | self.template( control ); |
||
| 271 | |||
| 272 | // Init the control. |
||
| 273 | kirki.input.radio.init( control ); |
||
| 274 | |||
| 275 | }, |
||
| 276 | |||
| 277 | /** |
||
| 278 | * Render the template. |
||
| 279 | * |
||
| 280 | * @since 3.0.17 |
||
| 281 | * @param {Object} control - The customizer control object. |
||
| 282 | * @param {Object} control.params - The control parameters. |
||
| 283 | * @param {string} control.params.label - The control label. |
||
| 284 | * @param {string} control.params.description - The control description. |
||
| 285 | * @param {string} control.params.inputAttrs - extra input arguments. |
||
| 286 | * @param {string} control.params.default - The default value. |
||
| 287 | * @param {Object} control.params.choices - Any extra choices we may need. |
||
| 288 | * @param {string} control.id - The setting. |
||
| 289 | * @returns {null} |
||
| 290 | */ |
||
| 291 | template: function( control ) { |
||
| 292 | var template = wp.template( 'kirki-input-radio' ); |
||
| 293 | control.container.html( template( { |
||
| 294 | label: control.params.label, |
||
| 295 | description: control.params.description, |
||
| 296 | 'data-id': control.id, |
||
| 297 | inputAttrs: control.params.inputAttrs, |
||
| 298 | 'default': control.params['default'], |
||
| 299 | value: kirki.setting.get( control.id ), |
||
| 300 | choices: control.params.choices |
||
| 301 | } ) ); |
||
| 302 | } |
||
| 303 | }, |
||
| 304 | |||
| 305 | /** |
||
| 306 | * The color control. |
||
| 307 | * |
||
| 308 | * @since 3.0.16 |
||
| 309 | */ |
||
| 310 | 'kirki-color': { |
||
| 311 | |||
| 312 | /** |
||
| 313 | * Init the control. |
||
| 314 | * |
||
| 315 | * @since 3.0.16 |
||
| 316 | * @param {Object} control - The customizer control object. |
||
| 317 | * @returns {null} |
||
| 318 | */ |
||
| 319 | init: function( control ) { |
||
| 320 | var self = this; |
||
| 321 | |||
| 322 | // Render the template. |
||
| 323 | self.template( control ); |
||
| 324 | |||
| 325 | // Init the control. |
||
| 326 | kirki.input.color.init( control ); |
||
| 327 | |||
| 328 | }, |
||
| 329 | |||
| 330 | /** |
||
| 331 | * Render the template. |
||
| 332 | * |
||
| 333 | * @since 3.0.16 |
||
| 334 | * @param {Object} control - The customizer control object. |
||
| 335 | * @param {Object} control.params - The control parameters. |
||
| 336 | * @param {string} control.params.label - The control label. |
||
| 337 | * @param {string} control.params.description - The control description. |
||
| 338 | * @param {string} control.params.mode - The colorpicker mode. Can be 'full' or 'hue'. |
||
| 339 | * @param {bool|array} control.params.palette - false if we don't want a palette, |
||
| 340 | * true to use the default palette, |
||
| 341 | * array of custom hex colors if we want a custom palette. |
||
| 342 | * @param {string} control.params.inputAttrs - extra input arguments. |
||
| 343 | * @param {string} control.params.default - The default value. |
||
| 344 | * @param {Object} control.params.choices - Any extra choices we may need. |
||
| 345 | * @param {boolean} control.params.choices.alpha - should we add an alpha channel? |
||
| 346 | * @param {string} control.id - The setting. |
||
| 347 | * @returns {null} |
||
| 348 | */ |
||
| 349 | template: function( control ) { |
||
| 350 | var template = wp.template( 'kirki-input-color' ); |
||
| 351 | control.container.html( template( { |
||
| 352 | label: control.params.label, |
||
| 353 | description: control.params.description, |
||
| 354 | 'data-id': control.id, |
||
| 355 | mode: control.params.mode, |
||
| 356 | inputAttrs: control.params.inputAttrs, |
||
| 357 | 'data-palette': control.params.palette, |
||
| 358 | 'data-default-color': control.params['default'], |
||
| 359 | 'data-alpha': control.params.choices.alpha, |
||
| 360 | value: kirki.setting.get( control.id ) |
||
| 361 | } ) ); |
||
| 362 | } |
||
| 363 | }, |
||
| 364 | |||
| 365 | /** |
||
| 366 | * The generic control. |
||
| 367 | * |
||
| 368 | * @since 3.0.16 |
||
| 369 | */ |
||
| 370 | 'kirki-generic': { |
||
| 371 | |||
| 372 | /** |
||
| 373 | * Init the control. |
||
| 374 | * |
||
| 375 | * @since 3.0.17 |
||
| 376 | * @param {Object} control - The customizer control object. |
||
| 377 | * @param {Object} control.params - Control parameters. |
||
| 378 | * @param {Object} control.params.choices - Define the specifics for this input. |
||
| 379 | * @param {string} control.params.choices.element - The HTML element we want to use ('input', 'div', 'span' etc). |
||
| 380 | * @returns {null} |
||
| 381 | */ |
||
| 382 | init: function( control ) { |
||
| 383 | var self = this; |
||
| 384 | |||
| 385 | // Render the template. |
||
| 386 | self.template( control ); |
||
| 387 | |||
| 388 | // Init the control. |
||
| 389 | if ( ! _.isUndefined( control.params ) && ! _.isUndefined( control.params.choices ) && ! _.isUndefined( control.params.choices.element ) && 'textarea' === control.params.choices.element ) { |
||
| 390 | kirki.input.textarea.init( control ); |
||
| 391 | return; |
||
| 392 | } |
||
| 393 | kirki.input.genericInput.init( control ); |
||
| 394 | }, |
||
| 395 | |||
| 396 | /** |
||
| 397 | * Render the template. |
||
| 398 | * |
||
| 399 | * @since 3.0.17 |
||
| 400 | * @param {Object} control - The customizer control object. |
||
| 401 | * @param {Object} control.params - The control parameters. |
||
| 402 | * @param {string} control.params.label - The control label. |
||
| 403 | * @param {string} control.params.description - The control description. |
||
| 404 | * @param {string} control.params.inputAttrs - extra input arguments. |
||
| 405 | * @param {string} control.params.default - The default value. |
||
| 406 | * @param {Object} control.params.choices - Any extra choices we may need. |
||
| 407 | * @param {boolean} control.params.choices.alpha - should we add an alpha channel? |
||
| 408 | * @param {string} control.id - The setting. |
||
| 409 | * @returns {null} |
||
| 410 | */ |
||
| 411 | template: function( control ) { |
||
| 412 | var args = { |
||
| 413 | label: control.params.label, |
||
| 414 | description: control.params.description, |
||
| 415 | 'data-id': control.id, |
||
| 416 | inputAttrs: control.params.inputAttrs, |
||
| 417 | choices: control.params.choices, |
||
| 418 | value: kirki.setting.get( control.id ) |
||
| 419 | }, |
||
| 420 | template; |
||
| 421 | |||
| 422 | if ( ! _.isUndefined( control.params ) && ! _.isUndefined( control.params.choices ) && ! _.isUndefined( control.params.choices.element ) && 'textarea' === control.params.choices.element ) { |
||
| 423 | template = wp.template( 'kirki-input-textarea' ); |
||
| 424 | control.container.html( template( args ) ); |
||
| 425 | return; |
||
| 426 | } |
||
| 427 | template = wp.template( 'kirki-input-generic' ); |
||
| 428 | control.container.html( template( args ) ); |
||
| 429 | } |
||
| 430 | }, |
||
| 431 | |||
| 432 | 'kirki-select': { |
||
| 433 | |||
| 434 | /** |
||
| 435 | * Init the control. |
||
| 436 | * |
||
| 437 | * @since 3.0.17 |
||
| 438 | * @param {Object} control - The customizer control object. |
||
| 439 | * @returns {null} |
||
| 440 | */ |
||
| 441 | init: function( control ) { |
||
| 442 | var self = this; |
||
| 443 | |||
| 444 | // Render the template. |
||
| 445 | self.template( control ); |
||
| 446 | |||
| 447 | // Init the control. |
||
| 448 | kirki.input.select.init( control ); |
||
| 449 | }, |
||
| 450 | |||
| 451 | /** |
||
| 452 | * Render the template. |
||
| 453 | * |
||
| 454 | * @since 3.0.17 |
||
| 455 | * @param {Object} control - The customizer control object. |
||
| 456 | * @param {Object} control.params - The control parameters. |
||
| 457 | * @param {string} control.params.label - The control label. |
||
| 458 | * @param {string} control.params.description - The control description. |
||
| 459 | * @param {string} control.params.inputAttrs - extra input arguments. |
||
| 460 | * @param {Object} control.params.default - The default value. |
||
| 461 | * @param {Object} control.params.choices - The choices for the select dropdown. |
||
| 462 | * @param {string} control.id - The setting. |
||
| 463 | * @returns {null} |
||
| 464 | */ |
||
| 465 | template: function( control ) { |
||
| 466 | var template = wp.template( 'kirki-input-select' ); |
||
| 467 | |||
| 468 | control.container.html( template( { |
||
| 469 | label: control.params.label, |
||
| 470 | description: control.params.description, |
||
| 471 | 'data-id': control.id, |
||
| 472 | inputAttrs: control.params.inputAttrs, |
||
| 473 | choices: control.params.choices, |
||
| 474 | value: kirki.setting.get( control.id ), |
||
| 475 | multiple: control.params.multiple || 1, |
||
| 476 | placeholder: control.params.placeholder |
||
| 477 | } ) ); |
||
| 478 | } |
||
| 479 | } |
||
| 480 | } |
||
| 481 | } ); |
||
| 482 | /* global kirkiL10n */ |
||
| 483 | var kirki = kirki || {}; |
||
| 484 | kirki = jQuery.extend( kirki, { |
||
| 485 | /** |
||
| 486 | * An object containing definitions for input fields. |
||
| 487 | * |
||
| 488 | * @since 3.0.16 |
||
| 489 | */ |
||
| 490 | input: { |
||
| 491 | |||
| 492 | /** |
||
| 493 | * Radio input fields. |
||
| 494 | * |
||
| 495 | * @since 3.0.17 |
||
| 496 | */ |
||
| 497 | radio: { |
||
| 498 | |||
| 499 | /** |
||
| 500 | * Init the control. |
||
| 501 | * |
||
| 502 | * @since 3.0.17 |
||
| 503 | * @param {Object} control - The control object. |
||
| 504 | * @param {Object} control.id - The setting. |
||
| 505 | * @returns {null} |
||
| 506 | */ |
||
| 507 | init: function( control ) { |
||
| 508 | var input = jQuery( 'input[data-id="' + control.id + '"]' ); |
||
| 509 | |||
| 510 | // Save the value |
||
| 511 | input.on( 'change keyup paste click', function() { |
||
| 512 | kirki.setting.set( control.id, jQuery( this ).val() ); |
||
| 513 | }); |
||
| 514 | } |
||
| 515 | }, |
||
| 516 | |||
| 517 | /** |
||
| 518 | * Color input fields. |
||
| 519 | * |
||
| 520 | * @since 3.0.16 |
||
| 521 | */ |
||
| 522 | color: { |
||
| 523 | |||
| 524 | /** |
||
| 525 | * Init the control. |
||
| 526 | * |
||
| 527 | * @since 3.0.16 |
||
| 528 | * @param {Object} control - The control object. |
||
| 529 | * @param {Object} control.id - The setting. |
||
| 530 | * @param {Object} control.choices - Additional options for the colorpickers. |
||
| 531 | * @param {Object} control.params - Control parameters. |
||
| 532 | * @param {Object} control.params.choices - alias for control.choices. |
||
| 533 | |||
| 534 | * @returns {null} |
||
| 535 | */ |
||
| 536 | init: function( control ) { |
||
| 537 | var picker = jQuery( '.kirki-color-control[data-id="' + control.id + '"]' ), |
||
| 538 | clear; |
||
| 539 | |||
| 540 | control.choices = control.choices || {}; |
||
| 541 | if ( _.isEmpty( control.choices ) && control.params.choices ) { |
||
| 542 | control.choices = control.params.choices; |
||
| 543 | } |
||
| 544 | |||
| 545 | // If we have defined any extra choices, make sure they are passed-on to Iris. |
||
| 546 | if ( ! _.isEmpty( control.choices ) ) { |
||
| 547 | picker.wpColorPicker( control.choices ); |
||
| 548 | } |
||
| 549 | |||
| 550 | // Tweaks to make the "clear" buttons work. |
||
| 551 | setTimeout( function() { |
||
| 552 | clear = jQuery( '.kirki-input-container[data-id="' + control.id + '"] .wp-picker-clear' ); |
||
| 553 | if ( clear.length ) { |
||
| 554 | clear.click( function() { |
||
| 555 | kirki.setting.set( control.id, '' ); |
||
| 556 | }); |
||
| 557 | } |
||
| 558 | }, 200 ); |
||
| 559 | |||
| 560 | // Saves our settings to the WP API |
||
| 561 | picker.wpColorPicker({ |
||
| 562 | change: function() { |
||
| 563 | |||
| 564 | // Small hack: the picker needs a small delay |
||
| 565 | setTimeout( function() { |
||
| 566 | kirki.setting.set( control.id, picker.val() ); |
||
| 567 | }, 20 ); |
||
| 568 | } |
||
| 569 | }); |
||
| 570 | } |
||
| 571 | }, |
||
| 572 | |||
| 573 | /** |
||
| 574 | * Generic input fields. |
||
| 575 | * |
||
| 576 | * @since 3.0.17 |
||
| 577 | */ |
||
| 578 | genericInput: { |
||
| 579 | |||
| 580 | /** |
||
| 581 | * Init the control. |
||
| 582 | * |
||
| 583 | * @since 3.0.17 |
||
| 584 | * @param {Object} control - The control object. |
||
| 585 | * @param {Object} control.id - The setting. |
||
| 586 | * @returns {null} |
||
| 587 | */ |
||
| 588 | init: function( control ) { |
||
| 589 | var input = jQuery( 'input[data-id="' + control.id + '"]' ); |
||
| 590 | |||
| 591 | // Save the value |
||
| 592 | input.on( 'change keyup paste click', function() { |
||
| 593 | kirki.setting.set( control.id, jQuery( this ).val() ); |
||
| 594 | }); |
||
| 595 | } |
||
| 596 | }, |
||
| 597 | |||
| 598 | /** |
||
| 599 | * Generic input fields. |
||
| 600 | * |
||
| 601 | * @since 3.0.17 |
||
| 602 | */ |
||
| 603 | textarea: { |
||
| 604 | |||
| 605 | /** |
||
| 606 | * Init the control. |
||
| 607 | * |
||
| 608 | * @since 3.0.17 |
||
| 609 | * @param {Object} control - The control object. |
||
| 610 | * @param {Object} control.id - The setting. |
||
| 611 | * @returns {null} |
||
| 612 | */ |
||
| 613 | init: function( control ) { |
||
| 614 | var textarea = jQuery( 'textarea[data-id="' + control.id + '"]' ); |
||
| 615 | |||
| 616 | // Save the value |
||
| 617 | textarea.on( 'change keyup paste click', function() { |
||
| 618 | kirki.setting.set( control.id, jQuery( this ).val() ); |
||
| 619 | }); |
||
| 620 | } |
||
| 621 | }, |
||
| 622 | |||
| 623 | select: { |
||
| 624 | |||
| 625 | /** |
||
| 626 | * Init the control. |
||
| 627 | * |
||
| 628 | * @since 3.0.17 |
||
| 629 | * @param {Object} control - The control object. |
||
| 630 | * @param {Object} control.id - The setting. |
||
| 631 | * @returns {null} |
||
| 632 | */ |
||
| 633 | init: function( control ) { |
||
| 634 | var element = jQuery( 'select[data-id="' + control.id + '"]' ), |
||
| 635 | multiple = parseInt( element.data( 'multiple' ), 10 ), |
||
| 636 | selectValue, |
||
| 637 | selectWooOptions = { |
||
| 638 | escapeMarkup: function( markup ) { |
||
| 639 | return markup; |
||
| 640 | } |
||
| 641 | }; |
||
| 642 | if ( control.params.placeholder ) { |
||
| 643 | selectWooOptions.placeholder = control.params.placeholder; |
||
| 644 | selectWooOptions.allowClear = true; |
||
| 645 | } |
||
| 646 | |||
| 647 | if ( 1 < multiple ) { |
||
| 648 | selectWooOptions.maximumSelectionLength = multiple; |
||
| 649 | } |
||
| 650 | jQuery( element ).selectWoo( selectWooOptions ).on( 'change', function() { |
||
| 651 | selectValue = jQuery( this ).val(); |
||
| 652 | selectValue = ( null === selectValue && 1 < multiple ) ? [] : selectValue; |
||
| 653 | kirki.setting.set( control.id, selectValue ); |
||
| 654 | }); |
||
| 655 | } |
||
| 656 | }, |
||
| 657 | |||
| 658 | image: { |
||
| 659 | |||
| 660 | /** |
||
| 661 | * Get the HTML for image inputs. |
||
| 662 | * |
||
| 663 | * @since 3.0.17 |
||
| 664 | * @param {Object} data - The arguments. |
||
| 665 | * @returns {string} |
||
| 666 | */ |
||
| 667 | View Code Duplication | getTemplate: function( data ) { |
|
| 668 | var html = '', |
||
| 669 | saveAs = 'url', |
||
| 670 | url; |
||
| 671 | |||
| 672 | data = _.defaults( data, { |
||
| 673 | label: '', |
||
| 674 | description: '', |
||
| 675 | inputAttrs: '', |
||
| 676 | 'data-id': '', |
||
| 677 | choices: {}, |
||
| 678 | value: '' |
||
| 679 | } ); |
||
| 680 | |||
| 681 | if ( ! _.isUndefined( data.choices ) && ! _.isUndefined( data.choices.save_as ) ) { |
||
| 682 | saveAs = data.choices.save_as; |
||
| 683 | } |
||
| 684 | url = data.value; |
||
| 685 | if ( _.isObject( data.value ) && ! _.isUndefined( data.value.url ) ) { |
||
| 686 | url = data.value.url; |
||
| 687 | } |
||
| 688 | |||
| 689 | html += '<label>'; |
||
| 690 | if ( data.label ) { |
||
| 691 | html += '<span class="customize-control-title">' + data.label + '</span>'; |
||
| 692 | } |
||
| 693 | if ( data.description ) { |
||
| 694 | html += '<span class="description customize-control-description">' + data.description + '</span>'; |
||
| 695 | } |
||
| 696 | html += '</label>'; |
||
| 697 | html += '<div class="image-wrapper attachment-media-view image-upload">'; |
||
| 698 | if ( data.value.url || '' !== url ) { |
||
| 699 | html += '<div class="thumbnail thumbnail-image"><img src="' + url + '" alt="" /></div>'; |
||
| 700 | } else { |
||
| 701 | html += '<div class="placeholder">' + kirkiL10n.noFileSelected + '</div>'; |
||
| 702 | } |
||
| 703 | html += '<div class="actions">'; |
||
| 704 | html += '<button class="button image-upload-remove-button' + ( '' === url ? ' hidden' : '' ) + '">' + kirkiL10n.remove + '</button>'; |
||
| 705 | if ( data['default'] && '' !== data['default'] ) { |
||
| 706 | html += '<button type="button" class="button image-default-button"'; |
||
| 707 | if ( data['default'] === data.value || ( ! _.isUndefined( data.value.url ) && data['default'] === data.value.url ) ) { |
||
| 708 | html += ' style="display:none;"'; |
||
| 709 | } |
||
| 710 | html += '>' + kirkiL10n['default'] + '</button>'; |
||
| 711 | } |
||
| 712 | html += '<button type="button" class="button image-upload-button">' + kirkiL10n.selectFile + '</button>'; |
||
| 713 | html += '</div></div>'; |
||
| 714 | |||
| 715 | return '<div class="kirki-input-container" data-id="' + data.id + '">' + html + '</div>'; |
||
| 716 | }, |
||
| 717 | |||
| 718 | /** |
||
| 719 | * Init the control. |
||
| 720 | * |
||
| 721 | * @since 3.0.17 |
||
| 722 | * @param {Object} control - The control object. |
||
| 723 | * @returns {null} |
||
| 724 | */ |
||
| 725 | init: function( control ) { // jshint ignore:line |
||
| 726 | } |
||
| 727 | } |
||
| 728 | } |
||
| 729 | } ); |
||
| 730 | var kirki = kirki || {}; |
||
| 731 | kirki = jQuery.extend( kirki, { |
||
| 732 | /** |
||
| 733 | * An object containing definitions for settings. |
||
| 734 | * |
||
| 735 | * @since 3.0.16 |
||
| 736 | */ |
||
| 737 | setting: { |
||
| 738 | |||
| 739 | /** |
||
| 740 | * Gets the value of a setting. |
||
| 741 | * |
||
| 742 | * This is a helper function that allows us to get the value of |
||
| 743 | * control[key1][key2] for example, when the setting used in the |
||
| 744 | * customizer API is "control". |
||
| 745 | * |
||
| 746 | * @since 3.0.16 |
||
| 747 | * @param {string} setting - The setting for which we're getting the value. |
||
| 748 | * @returns {mixed} Depends on the value. |
||
| 749 | */ |
||
| 750 | get: function( setting ) { |
||
| 751 | var parts = setting.split( '[' ), |
||
| 752 | foundSetting = '', |
||
| 753 | foundInStep = 0, |
||
| 754 | currentVal = ''; |
||
| 755 | |||
| 756 | _.each( parts, function( part, i ) { |
||
| 757 | part = part.replace( ']', '' ); |
||
| 758 | |||
| 759 | if ( 0 === i ) { |
||
| 760 | foundSetting = part; |
||
| 761 | } else { |
||
| 762 | foundSetting += '[' + part + ']'; |
||
| 763 | } |
||
| 764 | |||
| 765 | if ( ! _.isUndefined( wp.customize.instance( foundSetting ) ) ) { |
||
| 766 | currentVal = wp.customize.instance( foundSetting ).get(); |
||
| 767 | foundInStep = i; |
||
| 768 | } |
||
| 769 | |||
| 770 | if ( foundInStep < i ) { |
||
| 771 | if ( _.isObject( currentVal ) && ! _.isUndefined( currentVal[ part ] ) ) { |
||
| 772 | currentVal = currentVal[ part ]; |
||
| 773 | } |
||
| 774 | } |
||
| 775 | }); |
||
| 776 | |||
| 777 | return currentVal; |
||
| 778 | }, |
||
| 779 | |||
| 780 | /** |
||
| 781 | * Sets the value of a setting. |
||
| 782 | * |
||
| 783 | * This function is a bit complicated because there any many scenarios to consider. |
||
| 784 | * Example: We want to save the value for my_setting[something][3][something-else]. |
||
| 785 | * The control's setting is my_setting[something]. |
||
| 786 | * So we need to find that first, then figure out the remaining parts, |
||
| 787 | * merge the values recursively to avoid destroying my_setting[something][2] |
||
| 788 | * and also take into account any defined "key" arguments which take this even deeper. |
||
| 789 | * |
||
| 790 | * @since 3.0.16 |
||
| 791 | * @param {object|string} element - The DOM element whose value has changed, |
||
| 792 | * or an ID. |
||
| 793 | * @param {mixed} value - Depends on the control-type. |
||
| 794 | * @param {string} key - If we only want to save an item in an object |
||
| 795 | * we can define the key here. |
||
| 796 | * @returns {null} |
||
| 797 | */ |
||
| 798 | View Code Duplication | set: function( element, value, key ) { |
|
| 799 | var setting, |
||
| 800 | parts, |
||
| 801 | currentNode = '', |
||
| 802 | foundNode = '', |
||
| 803 | subSettingObj = {}, |
||
| 804 | currentVal, |
||
| 805 | subSetting, |
||
| 806 | subSettingParts; |
||
| 807 | |||
| 808 | // Get the setting from the element. |
||
| 809 | setting = element; |
||
| 810 | if ( _.isObject( element ) ) { |
||
| 811 | if ( jQuery( element ).attr( 'data-id' ) ) { |
||
| 812 | setting = element.attr( 'data-id' ); |
||
| 813 | } else { |
||
| 814 | setting = element.parents( '[data-id]' ).attr( 'data-id' ); |
||
| 815 | } |
||
| 816 | } |
||
| 817 | |||
| 818 | if ( 'undefined' !== typeof wp.customize.control( setting ) ) { |
||
| 819 | wp.customize.control( setting ).setting.set( value ); |
||
| 820 | return; |
||
| 821 | } |
||
| 822 | |||
| 823 | parts = setting.split( '[' ), |
||
| 824 | |||
| 825 | // Find the setting we're using in the control using the customizer API. |
||
| 826 | _.each( parts, function( part, i ) { |
||
| 827 | part = part.replace( ']', '' ); |
||
| 828 | |||
| 829 | // The current part of the setting. |
||
| 830 | currentNode = ( 0 === i ) ? part : '[' + part + ']'; |
||
| 831 | |||
| 832 | // When we find the node, get the value from it. |
||
| 833 | // In case of an object we'll need to merge with current values. |
||
| 834 | if ( ! _.isUndefined( wp.customize.instance( currentNode ) ) ) { |
||
| 835 | foundNode = currentNode; |
||
| 836 | currentVal = wp.customize.instance( foundNode ).get(); |
||
| 837 | } |
||
| 838 | } ); |
||
| 839 | |||
| 840 | // Get the remaining part of the setting that was unused. |
||
| 841 | subSetting = setting.replace( foundNode, '' ); |
||
| 842 | |||
| 843 | // If subSetting is not empty, then we're dealing with an object |
||
| 844 | // and we need to dig deeper and recursively merge the values. |
||
| 845 | if ( '' !== subSetting ) { |
||
| 846 | if ( ! _.isObject( currentVal ) ) { |
||
| 847 | currentVal = {}; |
||
| 848 | } |
||
| 849 | if ( '[' === subSetting.charAt( 0 ) ) { |
||
| 850 | subSetting = subSetting.replace( '[', '' ); |
||
| 851 | } |
||
| 852 | subSettingParts = subSetting.split( '[' ); |
||
| 853 | _.each( subSettingParts, function( subSettingPart, i ) { |
||
| 854 | subSettingParts[ i ] = subSettingPart.replace( ']', '' ); |
||
| 855 | } ); |
||
| 856 | |||
| 857 | // If using a key, we need to go 1 level deeper. |
||
| 858 | if ( key ) { |
||
| 859 | subSettingParts.push( key ); |
||
| 860 | } |
||
| 861 | |||
| 862 | // Converting to a JSON string and then parsing that to an object |
||
| 863 | // may seem a bit hacky and crude but it's efficient and works. |
||
| 864 | subSettingObj = '{"' + subSettingParts.join( '":{"' ) + '":"' + value + '"' + '}'.repeat( subSettingParts.length ); |
||
| 865 | subSettingObj = JSON.parse( subSettingObj ); |
||
| 866 | |||
| 867 | // Recursively merge with current value. |
||
| 868 | jQuery.extend( true, currentVal, subSettingObj ); |
||
| 869 | value = currentVal; |
||
| 870 | |||
| 871 | } else { |
||
| 872 | if ( key ) { |
||
| 873 | currentVal = ( ! _.isObject( currentVal ) ) ? {} : currentVal; |
||
| 874 | currentVal[ key ] = value; |
||
| 875 | value = currentVal; |
||
| 876 | } |
||
| 877 | } |
||
| 878 | wp.customize.control( foundNode ).setting.set( value ); |
||
| 879 | } |
||
| 880 | } |
||
| 881 | } ); |
||
| 882 | /* global ajaxurl */ |
||
| 883 | var kirki = kirki || {}; |
||
| 884 | kirki = jQuery.extend( kirki, { |
||
| 885 | /** |
||
| 886 | * A collection of utility methods. |
||
| 887 | * |
||
| 888 | * @since 3.0.17 |
||
| 889 | */ |
||
| 890 | util: { |
||
| 891 | |||
| 892 | /** |
||
| 893 | * A collection of utility methods for webfonts. |
||
| 894 | * |
||
| 895 | * @since 3.0.17 |
||
| 896 | */ |
||
| 897 | webfonts: { |
||
| 898 | |||
| 899 | /** |
||
| 900 | * Google-fonts related methods. |
||
| 901 | * |
||
| 902 | * @since 3.0.17 |
||
| 903 | */ |
||
| 904 | google: { |
||
| 905 | |||
| 906 | /** |
||
| 907 | * An object containing all Google fonts. |
||
| 908 | * |
||
| 909 | * to set this call this.setFonts(); |
||
| 910 | * |
||
| 911 | * @since 3.0.17 |
||
| 912 | */ |
||
| 913 | fonts: {}, |
||
| 914 | |||
| 915 | /** |
||
| 916 | * Init for google-fonts. |
||
| 917 | * |
||
| 918 | * @since 3.0.17 |
||
| 919 | * @returns {null} |
||
| 920 | */ |
||
| 921 | initialize: function() { |
||
| 922 | var self = this; |
||
| 923 | |||
| 924 | self.setFonts(); |
||
| 925 | }, |
||
| 926 | |||
| 927 | /** |
||
| 928 | * Set fonts in this.fonts |
||
| 929 | * |
||
| 930 | * @since 3.0.17 |
||
| 931 | * @returns {null} |
||
| 932 | */ |
||
| 933 | setFonts: function() { |
||
| 934 | var self = this; |
||
| 935 | |||
| 936 | // No need to run if we already have the fonts. |
||
| 937 | if ( ! _.isEmpty( self.fonts ) ) { |
||
| 938 | return; |
||
| 939 | } |
||
| 940 | |||
| 941 | // Make an AJAX call to set the fonts object (alpha). |
||
| 942 | jQuery.post( ajaxurl, { 'action': 'kirki_fonts_google_all_get' }, function( response ) { |
||
| 943 | |||
| 944 | // Get fonts from the JSON array. |
||
| 945 | self.fonts = JSON.parse( response ); |
||
| 946 | } ); |
||
| 947 | }, |
||
| 948 | |||
| 949 | /** |
||
| 950 | * Gets all properties of a font-family. |
||
| 951 | * |
||
| 952 | * @since 3.0.17 |
||
| 953 | * @param {string} family - The font-family we're interested in. |
||
| 954 | * @returns {Object} |
||
| 955 | */ |
||
| 956 | getFont: function( family ) { |
||
| 957 | var self = this, |
||
| 958 | fonts = self.getFonts(); |
||
| 959 | |||
| 960 | if ( 'undefined' === typeof fonts[ family ] ) { |
||
| 961 | return false; |
||
| 962 | } |
||
| 963 | return fonts[ family ]; |
||
| 964 | }, |
||
| 965 | |||
| 966 | /** |
||
| 967 | * Gets all properties of a font-family. |
||
| 968 | * |
||
| 969 | * @since 3.0.17 |
||
| 970 | * @param {string} order - How to order the fonts (alpha|popularity|trending). |
||
| 971 | * @param {int} number - How many to get. 0 for all. |
||
| 972 | * @returns {Object} |
||
| 973 | */ |
||
| 974 | getFonts: function( order, number ) { |
||
| 975 | var self = this, |
||
| 976 | ordered = {}, |
||
| 977 | partial = []; |
||
| 978 | |||
| 979 | // Make sure order is correct. |
||
| 980 | order = order || 'alpha'; |
||
| 981 | order = ( 'alpha' !== order && 'popularity' !== order && 'trending' !== order ) ? 'alpha' : order; |
||
| 982 | |||
| 983 | // Make sure number is correct. |
||
| 984 | number = number || 0; |
||
| 985 | number = parseInt( number, 10 ); |
||
| 986 | |||
| 987 | if ( 'alpha' === order || 0 === number ) { |
||
| 988 | ordered = self.fonts.items; |
||
| 989 | } else { |
||
| 990 | partial = _.first( self.fonts.order[ order ], number ); |
||
| 991 | _.each( partial, function( family ) { |
||
| 992 | ordered[ family ] = self.fonts.items[ family ]; |
||
| 993 | } ); |
||
| 994 | } |
||
| 995 | |||
| 996 | return ordered; |
||
| 997 | }, |
||
| 998 | |||
| 999 | /** |
||
| 1000 | * Gets the variants for a font-family. |
||
| 1001 | * |
||
| 1002 | * @since 3.0.17 |
||
| 1003 | * @param {string} family - The font-family we're interested in. |
||
| 1004 | * @returns {Array} |
||
| 1005 | */ |
||
| 1006 | getVariants: function( family ) { |
||
| 1007 | var self = this, |
||
| 1008 | font = self.getFont( family ); |
||
| 1009 | |||
| 1010 | // Early exit if font was not found. |
||
| 1011 | if ( ! font ) { |
||
| 1012 | return false; |
||
| 1013 | } |
||
| 1014 | |||
| 1015 | // Early exit if font doesn't have variants. |
||
| 1016 | if ( _.isUndefined( font.variants ) ) { |
||
| 1017 | return false; |
||
| 1018 | } |
||
| 1019 | |||
| 1020 | // Return the variants. |
||
| 1021 | return font.variants; |
||
| 1022 | }, |
||
| 1023 | |||
| 1024 | /** |
||
| 1025 | * Get the subsets for a font-family. |
||
| 1026 | * |
||
| 1027 | * @since 3.0.17 |
||
| 1028 | * @param {string} family - The font-family we're interested in. |
||
| 1029 | * @returns {Object} |
||
| 1030 | */ |
||
| 1031 | getSubsets: function( family ) { |
||
| 1032 | var self = this, |
||
| 1033 | font = self.getFont( family ); |
||
| 1034 | |||
| 1035 | // Early exit if font was not found. |
||
| 1036 | if ( ! font ) { |
||
| 1037 | return false; |
||
| 1038 | } |
||
| 1039 | |||
| 1040 | // Early exit if font doesn't have subsets. |
||
| 1041 | if ( _.isUndefined( font.subsets ) ) { |
||
| 1042 | return false; |
||
| 1043 | } |
||
| 1044 | |||
| 1045 | // Return the variants. |
||
| 1046 | return font.subsets; |
||
| 1047 | } |
||
| 1048 | }, |
||
| 1049 | |||
| 1050 | /** |
||
| 1051 | * Standard fonts related methods. |
||
| 1052 | * |
||
| 1053 | * @since 3.0.17 |
||
| 1054 | */ |
||
| 1055 | standard: { |
||
| 1056 | |||
| 1057 | /** |
||
| 1058 | * An object containing all Standard fonts. |
||
| 1059 | * |
||
| 1060 | * to set this call this.setFonts(); |
||
| 1061 | * |
||
| 1062 | * @since 3.0.17 |
||
| 1063 | */ |
||
| 1064 | fonts: {}, |
||
| 1065 | |||
| 1066 | /** |
||
| 1067 | * Init for google-fonts. |
||
| 1068 | * |
||
| 1069 | * @since 3.0.17 |
||
| 1070 | * @returns {null} |
||
| 1071 | */ |
||
| 1072 | initialize: function() { |
||
| 1073 | var self = this; |
||
| 1074 | |||
| 1075 | self.setFonts(); |
||
| 1076 | }, |
||
| 1077 | |||
| 1078 | /** |
||
| 1079 | * Set fonts in this.fonts |
||
| 1080 | * |
||
| 1081 | * @since 3.0.17 |
||
| 1082 | * @returns {null} |
||
| 1083 | */ |
||
| 1084 | setFonts: function() { |
||
| 1085 | var self = this; |
||
| 1086 | |||
| 1087 | // No need to run if we already have the fonts. |
||
| 1088 | if ( ! _.isEmpty( self.fonts ) ) { |
||
| 1089 | return; |
||
| 1090 | } |
||
| 1091 | |||
| 1092 | // Make an AJAX call to set the fonts object. |
||
| 1093 | jQuery.post( ajaxurl, { 'action': 'kirki_fonts_standard_all_get' }, function( response ) { |
||
| 1094 | |||
| 1095 | // Get fonts from the JSON array. |
||
| 1096 | self.fonts = JSON.parse( response ); |
||
| 1097 | } ); |
||
| 1098 | }, |
||
| 1099 | |||
| 1100 | /** |
||
| 1101 | * Gets the variants for a font-family. |
||
| 1102 | * |
||
| 1103 | * @since 3.0.17 |
||
| 1104 | * @returns {Array} |
||
| 1105 | */ |
||
| 1106 | getVariants: function( family ) { // jshint ignore: line |
||
| 1107 | return ['regular', 'italic', '700', '700italic']; |
||
| 1108 | } |
||
| 1109 | }, |
||
| 1110 | |||
| 1111 | /** |
||
| 1112 | * Figure out what this font-family is (google/standard) |
||
| 1113 | * |
||
| 1114 | * @since 3.0.20 |
||
| 1115 | * @param {string} family - The font-family. |
||
| 1116 | * @returns {string|false} - Returns string if found (google|standard) |
||
| 1117 | * and false in case the font-family is an arbitrary value |
||
| 1118 | * not found anywhere in our font definitions. |
||
| 1119 | */ |
||
| 1120 | getFontType: function( family ) { |
||
| 1121 | var self = this; |
||
| 1122 | |||
| 1123 | // Check for standard fonts first. |
||
| 1124 | if ( |
||
| 1125 | 'undefined' !== typeof self.standard.fonts[ family ] || ( |
||
| 1126 | 'undefined' !== typeof self.standard.fonts.stack && |
||
| 1127 | 'undefined' !== typeof self.standard.fonts.stack[ family ] |
||
| 1128 | ) |
||
| 1129 | ) { |
||
| 1130 | return 'standard'; |
||
| 1131 | } |
||
| 1132 | |||
| 1133 | // Check in googlefonts. |
||
| 1134 | if ( 'undefined' !== typeof self.google.fonts.items[ family ] ) { |
||
| 1135 | return 'google'; |
||
| 1136 | } |
||
| 1137 | return false; |
||
| 1138 | } |
||
| 1139 | } |
||
| 1140 | } |
||
| 1141 | } ); |
||
| 1142 | /* global kirki */ |
||
| 1143 | /** |
||
| 1144 | * The majority of the code in this file |
||
| 1145 | * is derived from the wp-customize-posts plugin |
||
| 1146 | * and the work of @westonruter to whom I am very grateful. |
||
| 1147 | * |
||
| 1148 | * @see https://github.com/xwp/wp-customize-posts |
||
| 1149 | */ |
||
| 1150 | |||
| 1151 | View Code Duplication | ( function() { |
|
| 1152 | 'use strict'; |
||
| 1153 | |||
| 1154 | /** |
||
| 1155 | * A dynamic color-alpha control. |
||
| 1156 | * |
||
| 1157 | * @class |
||
| 1158 | * @augments wp.customize.Control |
||
| 1159 | * @augments wp.customize.Class |
||
| 1160 | */ |
||
| 1161 | wp.customize.kirkiDynamicControl = wp.customize.Control.extend({ |
||
| 1162 | |||
| 1163 | initialize: function( id, options ) { |
||
| 1164 | var control = this, |
||
| 1165 | args = options || {}; |
||
| 1166 | |||
| 1167 | args.params = args.params || {}; |
||
| 1168 | if ( ! args.params.type ) { |
||
| 1169 | args.params.type = 'kirki-generic'; |
||
| 1170 | } |
||
| 1171 | if ( ! args.params.content ) { |
||
| 1172 | args.params.content = jQuery( '<li></li>' ); |
||
| 1173 | args.params.content.attr( 'id', 'customize-control-' + id.replace( /]/g, '' ).replace( /\[/g, '-' ) ); |
||
| 1174 | args.params.content.attr( 'class', 'customize-control customize-control-' + args.params.type ); |
||
| 1175 | } |
||
| 1176 | |||
| 1177 | control.propertyElements = []; |
||
| 1178 | wp.customize.Control.prototype.initialize.call( control, id, args ); |
||
| 1179 | }, |
||
| 1180 | |||
| 1181 | /** |
||
| 1182 | * Add bidirectional data binding links between inputs and the setting(s). |
||
| 1183 | * |
||
| 1184 | * This is copied from wp.customize.Control.prototype.initialize(). It |
||
| 1185 | * should be changed in Core to be applied once the control is embedded. |
||
| 1186 | * |
||
| 1187 | * @private |
||
| 1188 | * @returns {null} |
||
| 1189 | */ |
||
| 1190 | _setUpSettingRootLinks: function() { |
||
| 1191 | var control = this, |
||
| 1192 | nodes = control.container.find( '[data-customize-setting-link]' ); |
||
| 1193 | |||
| 1194 | nodes.each( function() { |
||
| 1195 | var node = jQuery( this ); |
||
| 1196 | |||
| 1197 | wp.customize( node.data( 'customizeSettingLink' ), function( setting ) { |
||
| 1198 | var element = new wp.customize.Element( node ); |
||
| 1199 | control.elements.push( element ); |
||
| 1200 | element.sync( setting ); |
||
| 1201 | element.set( setting() ); |
||
| 1202 | }); |
||
| 1203 | }); |
||
| 1204 | }, |
||
| 1205 | |||
| 1206 | /** |
||
| 1207 | * Add bidirectional data binding links between inputs and the setting properties. |
||
| 1208 | * |
||
| 1209 | * @private |
||
| 1210 | * @returns {null} |
||
| 1211 | */ |
||
| 1212 | _setUpSettingPropertyLinks: function() { |
||
| 1213 | var control = this, |
||
| 1214 | nodes; |
||
| 1215 | |||
| 1216 | if ( ! control.setting ) { |
||
| 1217 | return; |
||
| 1218 | } |
||
| 1219 | |||
| 1220 | nodes = control.container.find( '[data-customize-setting-property-link]' ); |
||
| 1221 | |||
| 1222 | nodes.each( function() { |
||
| 1223 | var node = jQuery( this ), |
||
| 1224 | element, |
||
| 1225 | propertyName = node.data( 'customizeSettingPropertyLink' ); |
||
| 1226 | |||
| 1227 | element = new wp.customize.Element( node ); |
||
| 1228 | control.propertyElements.push( element ); |
||
| 1229 | element.set( control.setting()[ propertyName ] ); |
||
| 1230 | |||
| 1231 | element.bind( function( newPropertyValue ) { |
||
| 1232 | var newSetting = control.setting(); |
||
| 1233 | if ( newPropertyValue === newSetting[ propertyName ] ) { |
||
| 1234 | return; |
||
| 1235 | } |
||
| 1236 | newSetting = _.clone( newSetting ); |
||
| 1237 | newSetting[ propertyName ] = newPropertyValue; |
||
| 1238 | control.setting.set( newSetting ); |
||
| 1239 | } ); |
||
| 1240 | control.setting.bind( function( newValue ) { |
||
| 1241 | if ( newValue[ propertyName ] !== element.get() ) { |
||
| 1242 | element.set( newValue[ propertyName ] ); |
||
| 1243 | } |
||
| 1244 | } ); |
||
| 1245 | }); |
||
| 1246 | }, |
||
| 1247 | |||
| 1248 | /** |
||
| 1249 | * @inheritdoc |
||
| 1250 | */ |
||
| 1251 | ready: function() { |
||
| 1252 | var control = this; |
||
| 1253 | |||
| 1254 | control._setUpSettingRootLinks(); |
||
| 1255 | control._setUpSettingPropertyLinks(); |
||
| 1256 | |||
| 1257 | wp.customize.Control.prototype.ready.call( control ); |
||
| 1258 | |||
| 1259 | control.deferred.embedded.done( function() { |
||
| 1260 | control.initKirkiControl( control ); |
||
| 1261 | }); |
||
| 1262 | }, |
||
| 1263 | |||
| 1264 | /** |
||
| 1265 | * Embed the control in the document. |
||
| 1266 | * |
||
| 1267 | * Override the embed() method to do nothing, |
||
| 1268 | * so that the control isn't embedded on load, |
||
| 1269 | * unless the containing section is already expanded. |
||
| 1270 | * |
||
| 1271 | * @returns {null} |
||
| 1272 | */ |
||
| 1273 | embed: function() { |
||
| 1274 | var control = this, |
||
| 1275 | sectionId = control.section(); |
||
| 1276 | |||
| 1277 | if ( ! sectionId ) { |
||
| 1278 | return; |
||
| 1279 | } |
||
| 1280 | |||
| 1281 | wp.customize.section( sectionId, function( section ) { |
||
| 1282 | if ( 'kirki-expanded' === section.params.type || section.expanded() || wp.customize.settings.autofocus.control === control.id ) { |
||
| 1283 | control.actuallyEmbed(); |
||
| 1284 | } else { |
||
| 1285 | section.expanded.bind( function( expanded ) { |
||
| 1286 | if ( expanded ) { |
||
| 1287 | control.actuallyEmbed(); |
||
| 1288 | } |
||
| 1289 | } ); |
||
| 1290 | } |
||
| 1291 | } ); |
||
| 1292 | }, |
||
| 1293 | |||
| 1294 | /** |
||
| 1295 | * Deferred embedding of control when actually |
||
| 1296 | * |
||
| 1297 | * This function is called in Section.onChangeExpanded() so the control |
||
| 1298 | * will only get embedded when the Section is first expanded. |
||
| 1299 | * |
||
| 1300 | * @returns {null} |
||
| 1301 | */ |
||
| 1302 | actuallyEmbed: function() { |
||
| 1303 | var control = this; |
||
| 1304 | if ( 'resolved' === control.deferred.embedded.state() ) { |
||
| 1305 | return; |
||
| 1306 | } |
||
| 1307 | control.renderContent(); |
||
| 1308 | control.deferred.embedded.resolve(); // This triggers control.ready(). |
||
| 1309 | }, |
||
| 1310 | |||
| 1311 | /** |
||
| 1312 | * This is not working with autofocus. |
||
| 1313 | * |
||
| 1314 | * @param {object} [args] Args. |
||
| 1315 | * @returns {null} |
||
| 1316 | */ |
||
| 1317 | focus: function( args ) { |
||
| 1318 | var control = this; |
||
| 1319 | control.actuallyEmbed(); |
||
| 1320 | wp.customize.Control.prototype.focus.call( control, args ); |
||
| 1321 | }, |
||
| 1322 | |||
| 1323 | /** |
||
| 1324 | * Additional actions that run on ready. |
||
| 1325 | * |
||
| 1326 | * @param {object} [args] Args. |
||
| 1327 | * @returns {null} |
||
| 1328 | */ |
||
| 1329 | initKirkiControl: function( control ) { |
||
| 1330 | if ( 'undefined' !== typeof kirki.control[ control.params.type ] ) { |
||
| 1331 | kirki.control[ control.params.type ].init( control ); |
||
| 1332 | return; |
||
| 1333 | } |
||
| 1334 | |||
| 1335 | // Save the value |
||
| 1336 | this.container.on( 'change keyup paste click', 'input', function() { |
||
| 1337 | control.setting.set( jQuery( this ).val() ); |
||
| 1338 | }); |
||
| 1339 | }, |
||
| 1340 | |||
| 1341 | kirkiValidateCSSValue: function( value ) { |
||
| 1342 | |||
| 1343 | var validUnits = ['rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax'], |
||
| 1344 | numericValue, |
||
| 1345 | unit; |
||
| 1346 | |||
| 1347 | // 0 is always a valid value, and we can't check calc() values effectively. |
||
| 1348 | if ( '0' === value || ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) ) { |
||
| 1349 | return true; |
||
| 1350 | } |
||
| 1351 | |||
| 1352 | if ( 'auto' === value || 'inherit' === value || 'initial' === value ) { |
||
| 1353 | return true; |
||
| 1354 | } |
||
| 1355 | |||
| 1356 | // Get the numeric value. |
||
| 1357 | numericValue = parseFloat( value ); |
||
| 1358 | |||
| 1359 | // Get the unit |
||
| 1360 | unit = value.replace( numericValue, '' ); |
||
| 1361 | |||
| 1362 | // Check the validity of the numeric value and units. |
||
| 1363 | if ( isNaN( numericValue ) || -1 === jQuery.inArray( unit, validUnits ) ) { |
||
| 1364 | return false; |
||
| 1365 | } |
||
| 1366 | return true; |
||
| 1367 | } |
||
| 1368 | }); |
||
| 1369 | })(); |
||
| 1370 | |||
| 1371 | _.each( kirki.control, function( obj, type ) { |
||
| 1372 | wp.customize.controlConstructor[ type ] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 1373 | } ); |
||
| 1374 | /* global kirkiControlLoader */ |
||
| 1375 | wp.customize.controlConstructor['kirki-background'] = wp.customize.Control.extend({ |
||
| 1376 | |||
| 1377 | // When we're finished loading continue processing |
||
| 1378 | ready: function() { |
||
| 1379 | |||
| 1380 | 'use strict'; |
||
| 1381 | |||
| 1382 | var control = this; |
||
| 1383 | |||
| 1384 | // Init the control. |
||
| 1385 | if ( ! _.isUndefined( window.kirkiControlLoader ) && _.isFunction( kirkiControlLoader ) ) { |
||
| 1386 | kirkiControlLoader( control ); |
||
| 1387 | } else { |
||
| 1388 | control.initKirkiControl(); |
||
| 1389 | } |
||
| 1390 | }, |
||
| 1391 | |||
| 1392 | View Code Duplication | initKirkiControl: function() { |
|
| 1393 | |||
| 1394 | var control = this, |
||
| 1395 | value = control.setting._value, |
||
| 1396 | picker = control.container.find( '.kirki-color-control' ); |
||
| 1397 | |||
| 1398 | // Hide unnecessary controls if the value doesn't have an image. |
||
| 1399 | if ( _.isUndefined( value['background-image'] ) || '' === value['background-image'] ) { |
||
| 1400 | control.container.find( '.background-wrapper > .background-repeat' ).hide(); |
||
| 1401 | control.container.find( '.background-wrapper > .background-position' ).hide(); |
||
| 1402 | control.container.find( '.background-wrapper > .background-size' ).hide(); |
||
| 1403 | control.container.find( '.background-wrapper > .background-attachment' ).hide(); |
||
| 1404 | } |
||
| 1405 | |||
| 1406 | // Color. |
||
| 1407 | picker.wpColorPicker({ |
||
| 1408 | change: function() { |
||
| 1409 | setTimeout( function() { |
||
| 1410 | control.saveValue( 'background-color', picker.val() ); |
||
| 1411 | }, 100 ); |
||
| 1412 | } |
||
| 1413 | }); |
||
| 1414 | |||
| 1415 | // Background-Repeat. |
||
| 1416 | control.container.on( 'change', '.background-repeat select', function() { |
||
| 1417 | control.saveValue( 'background-repeat', jQuery( this ).val() ); |
||
| 1418 | }); |
||
| 1419 | |||
| 1420 | // Background-Size. |
||
| 1421 | control.container.on( 'change click', '.background-size input', function() { |
||
| 1422 | control.saveValue( 'background-size', jQuery( this ).val() ); |
||
| 1423 | }); |
||
| 1424 | |||
| 1425 | // Background-Position. |
||
| 1426 | control.container.on( 'change', '.background-position select', function() { |
||
| 1427 | control.saveValue( 'background-position', jQuery( this ).val() ); |
||
| 1428 | }); |
||
| 1429 | |||
| 1430 | // Background-Attachment. |
||
| 1431 | control.container.on( 'change click', '.background-attachment input', function() { |
||
| 1432 | control.saveValue( 'background-attachment', jQuery( this ).val() ); |
||
| 1433 | }); |
||
| 1434 | |||
| 1435 | // Background-Image. |
||
| 1436 | control.container.on( 'click', '.background-image-upload-button', function( e ) { |
||
| 1437 | var image = wp.media({ multiple: false }).open().on( 'select', function() { |
||
| 1438 | |||
| 1439 | // This will return the selected image from the Media Uploader, the result is an object. |
||
| 1440 | var uploadedImage = image.state().get( 'selection' ).first(), |
||
| 1441 | previewImage = uploadedImage.toJSON().sizes.full.url, |
||
| 1442 | imageUrl, |
||
| 1443 | imageID, |
||
| 1444 | imageWidth, |
||
| 1445 | imageHeight, |
||
| 1446 | preview, |
||
| 1447 | removeButton; |
||
| 1448 | |||
| 1449 | if ( ! _.isUndefined( uploadedImage.toJSON().sizes.medium ) ) { |
||
| 1450 | previewImage = uploadedImage.toJSON().sizes.medium.url; |
||
| 1451 | } else if ( ! _.isUndefined( uploadedImage.toJSON().sizes.thumbnail ) ) { |
||
| 1452 | previewImage = uploadedImage.toJSON().sizes.thumbnail.url; |
||
| 1453 | } |
||
| 1454 | |||
| 1455 | imageUrl = uploadedImage.toJSON().sizes.full.url; |
||
| 1456 | imageID = uploadedImage.toJSON().id; |
||
| 1457 | imageWidth = uploadedImage.toJSON().width; |
||
| 1458 | imageHeight = uploadedImage.toJSON().height; |
||
| 1459 | |||
| 1460 | // Show extra controls if the value has an image. |
||
| 1461 | if ( '' !== imageUrl ) { |
||
| 1462 | control.container.find( '.background-wrapper > .background-repeat, .background-wrapper > .background-position, .background-wrapper > .background-size, .background-wrapper > .background-attachment' ).show(); |
||
| 1463 | } |
||
| 1464 | |||
| 1465 | control.saveValue( 'background-image', imageUrl ); |
||
| 1466 | preview = control.container.find( '.placeholder, .thumbnail' ); |
||
| 1467 | removeButton = control.container.find( '.background-image-upload-remove-button' ); |
||
| 1468 | |||
| 1469 | if ( preview.length ) { |
||
| 1470 | preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '<img src="' + previewImage + '" alt="" />' ); |
||
| 1471 | } |
||
| 1472 | if ( removeButton.length ) { |
||
| 1473 | removeButton.show(); |
||
| 1474 | } |
||
| 1475 | }); |
||
| 1476 | |||
| 1477 | e.preventDefault(); |
||
| 1478 | }); |
||
| 1479 | |||
| 1480 | control.container.on( 'click', '.background-image-upload-remove-button', function( e ) { |
||
| 1481 | |||
| 1482 | var preview, |
||
| 1483 | removeButton; |
||
| 1484 | |||
| 1485 | e.preventDefault(); |
||
| 1486 | |||
| 1487 | control.saveValue( 'background-image', '' ); |
||
| 1488 | |||
| 1489 | preview = control.container.find( '.placeholder, .thumbnail' ); |
||
| 1490 | removeButton = control.container.find( '.background-image-upload-remove-button' ); |
||
| 1491 | |||
| 1492 | // Hide unnecessary controls. |
||
| 1493 | control.container.find( '.background-wrapper > .background-repeat' ).hide(); |
||
| 1494 | control.container.find( '.background-wrapper > .background-position' ).hide(); |
||
| 1495 | control.container.find( '.background-wrapper > .background-size' ).hide(); |
||
| 1496 | control.container.find( '.background-wrapper > .background-attachment' ).hide(); |
||
| 1497 | |||
| 1498 | if ( preview.length ) { |
||
| 1499 | preview.removeClass().addClass( 'placeholder' ).html( 'No file selected' ); |
||
| 1500 | } |
||
| 1501 | if ( removeButton.length ) { |
||
| 1502 | removeButton.hide(); |
||
| 1503 | } |
||
| 1504 | }); |
||
| 1505 | }, |
||
| 1506 | |||
| 1507 | /** |
||
| 1508 | * Saves the value. |
||
| 1509 | */ |
||
| 1510 | saveValue: function( property, value ) { |
||
| 1511 | |||
| 1512 | var control = this, |
||
| 1513 | input = jQuery( '#customize-control-' + control.id.replace( '[', '-' ).replace( ']', '' ) + ' .background-hidden-value' ), |
||
| 1514 | val = control.setting._value; |
||
| 1515 | |||
| 1516 | val[ property ] = value; |
||
| 1517 | |||
| 1518 | jQuery( input ).attr( 'value', JSON.stringify( val ) ).trigger( 'change' ); |
||
| 1519 | control.setting.set( val ); |
||
| 1520 | } |
||
| 1521 | }); |
||
| 1522 | wp.customize.controlConstructor['kirki-color-palette'] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 1523 | wp.customize.controlConstructor['kirki-dashicons'] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 1524 | wp.customize.controlConstructor['kirki-date'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1525 | |||
| 1526 | initKirkiControl: function() { |
||
| 1527 | |||
| 1528 | var control = this; |
||
| 1529 | |||
| 1530 | // Only add in WP 4.9+. |
||
| 1531 | if ( _.isUndefined( wp.customize.DateTimeControl ) ) { |
||
| 1532 | return; |
||
| 1533 | } |
||
| 1534 | |||
| 1535 | // New method for the DateTime control. |
||
| 1536 | wp.customize.control.add( new wp.customize.DateTimeControl( control.id, { |
||
| 1537 | section: control.params.section, |
||
| 1538 | priority: control.params.priority, |
||
| 1539 | label: control.params.label, |
||
| 1540 | description: control.params.description, |
||
| 1541 | settings: { 'default': control.id }, |
||
| 1542 | 'default': control.params['default'] |
||
| 1543 | } ) ); |
||
| 1544 | } |
||
| 1545 | }); |
||
| 1546 | /* global dimensionkirkiL10n */ |
||
| 1547 | wp.customize.controlConstructor['kirki-dimension'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1548 | |||
| 1549 | initKirkiControl: function() { |
||
| 1550 | |||
| 1551 | var control = this, |
||
| 1552 | value; |
||
| 1553 | |||
| 1554 | // Notifications. |
||
| 1555 | control.kirkiNotifications(); |
||
| 1556 | |||
| 1557 | // Save the value |
||
| 1558 | this.container.on( 'change keyup paste', 'input', function() { |
||
| 1559 | |||
| 1560 | value = jQuery( this ).val(); |
||
| 1561 | control.setting.set( value ); |
||
| 1562 | }); |
||
| 1563 | }, |
||
| 1564 | |||
| 1565 | /** |
||
| 1566 | * Handles notifications. |
||
| 1567 | */ |
||
| 1568 | kirkiNotifications: function() { |
||
| 1569 | |||
| 1570 | var control = this; |
||
| 1571 | |||
| 1572 | wp.customize( control.id, function( setting ) { |
||
| 1573 | setting.bind( function( value ) { |
||
| 1574 | var code = 'long_title'; |
||
| 1575 | |||
| 1576 | if ( false === control.kirkiValidateCSSValue( value ) ) { |
||
| 1577 | setting.notifications.add( code, new wp.customize.Notification( |
||
| 1578 | code, |
||
| 1579 | { |
||
| 1580 | type: 'warning', |
||
| 1581 | message: dimensionkirkiL10n['invalid-value'] |
||
| 1582 | } |
||
| 1583 | ) ); |
||
| 1584 | } else { |
||
| 1585 | setting.notifications.remove( code ); |
||
| 1586 | } |
||
| 1587 | } ); |
||
| 1588 | } ); |
||
| 1589 | } |
||
| 1590 | }); |
||
| 1591 | /* global dimensionskirkiL10n */ |
||
| 1592 | wp.customize.controlConstructor['kirki-dimensions'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1593 | |||
| 1594 | initKirkiControl: function() { |
||
| 1595 | |||
| 1596 | var control = this, |
||
| 1597 | subControls = control.params.choices.controls, |
||
| 1598 | value = {}, |
||
| 1599 | subsArray = [], |
||
| 1600 | i; |
||
| 1601 | |||
| 1602 | _.each( subControls, function( v, i ) { |
||
| 1603 | if ( true === v ) { |
||
| 1604 | subsArray.push( i ); |
||
| 1605 | } |
||
| 1606 | } ); |
||
| 1607 | |||
| 1608 | for ( i = 0; i < subsArray.length; i++ ) { |
||
| 1609 | value[ subsArray[ i ] ] = control.setting._value[ subsArray[ i ] ]; |
||
| 1610 | control.updateDimensionsValue( subsArray[ i ], value ); |
||
| 1611 | } |
||
| 1612 | }, |
||
| 1613 | |||
| 1614 | /** |
||
| 1615 | * Updates the value. |
||
| 1616 | */ |
||
| 1617 | updateDimensionsValue: function( context, value ) { |
||
| 1618 | |||
| 1619 | var control = this; |
||
| 1620 | |||
| 1621 | control.container.on( 'change keyup paste', '.' + context + ' input', function() { |
||
| 1622 | value[ context ] = jQuery( this ).val(); |
||
| 1623 | |||
| 1624 | // Notifications. |
||
| 1625 | control.kirkiNotifications(); |
||
| 1626 | |||
| 1627 | // Save the value |
||
| 1628 | control.saveValue( value ); |
||
| 1629 | }); |
||
| 1630 | }, |
||
| 1631 | |||
| 1632 | /** |
||
| 1633 | * Saves the value. |
||
| 1634 | */ |
||
| 1635 | saveValue: function( value ) { |
||
| 1636 | |||
| 1637 | var control = this, |
||
| 1638 | newValue = {}; |
||
| 1639 | |||
| 1640 | _.each( value, function( newSubValue, i ) { |
||
| 1641 | newValue[ i ] = newSubValue; |
||
| 1642 | }); |
||
| 1643 | |||
| 1644 | control.setting.set( newValue ); |
||
| 1645 | }, |
||
| 1646 | |||
| 1647 | /** |
||
| 1648 | * Handles notifications. |
||
| 1649 | */ |
||
| 1650 | kirkiNotifications: function() { |
||
| 1651 | |||
| 1652 | var control = this; |
||
| 1653 | |||
| 1654 | wp.customize( control.id, function( setting ) { |
||
| 1655 | setting.bind( function( value ) { |
||
| 1656 | var code = 'long_title', |
||
| 1657 | subs = {}, |
||
| 1658 | message; |
||
| 1659 | |||
| 1660 | setting.notifications.remove( code ); |
||
| 1661 | |||
| 1662 | _.each( value, function( val, direction ) { |
||
| 1663 | if ( false === control.kirkiValidateCSSValue( val ) ) { |
||
| 1664 | subs[ direction ] = val; |
||
| 1665 | } else { |
||
| 1666 | delete subs[ direction ]; |
||
| 1667 | } |
||
| 1668 | } ); |
||
| 1669 | |||
| 1670 | if ( ! _.isEmpty( subs ) ) { |
||
| 1671 | message = dimensionskirkiL10n['invalid-value'] + ' (' + _.values( subs ).toString() + ') '; |
||
| 1672 | setting.notifications.add( code, new wp.customize.Notification( code, { |
||
| 1673 | type: 'warning', |
||
| 1674 | message: message |
||
| 1675 | } ) ); |
||
| 1676 | return; |
||
| 1677 | } |
||
| 1678 | setting.notifications.remove( code ); |
||
| 1679 | } ); |
||
| 1680 | } ); |
||
| 1681 | } |
||
| 1682 | }); |
||
| 1683 | /* global tinyMCE */ |
||
| 1684 | wp.customize.controlConstructor['kirki-editor'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1685 | |||
| 1686 | initKirkiControl: function() { |
||
| 1687 | |||
| 1688 | var control = this, |
||
| 1689 | element = control.container.find( 'textarea' ), |
||
| 1690 | id = 'kirki-editor-' + control.id.replace( '[', '' ).replace( ']', '' ), |
||
| 1691 | editor; |
||
| 1692 | |||
| 1693 | wp.editor.initialize( id, { |
||
| 1694 | tinymce: { |
||
| 1695 | wpautop: true |
||
| 1696 | }, |
||
| 1697 | quicktags: true, |
||
| 1698 | mediaButtons: true |
||
| 1699 | }); |
||
| 1700 | |||
| 1701 | editor = tinyMCE.get( id ); |
||
| 1702 | |||
| 1703 | if ( editor ) { |
||
| 1704 | editor.onChange.add( function( ed ) { |
||
| 1705 | var content; |
||
| 1706 | |||
| 1707 | ed.save(); |
||
| 1708 | content = editor.getContent(); |
||
| 1709 | element.val( content ).trigger( 'change' ); |
||
| 1710 | wp.customize.instance( control.id ).set( content ); |
||
| 1711 | }); |
||
| 1712 | } |
||
| 1713 | } |
||
| 1714 | }); |
||
| 1715 | /* global fontAwesomeJSON */ |
||
| 1716 | wp.customize.controlConstructor['kirki-fontawesome'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1717 | |||
| 1718 | View Code Duplication | initKirkiControl: function() { |
|
| 1719 | |||
| 1720 | var control = this, |
||
| 1721 | element = this.container.find( 'select' ), |
||
| 1722 | icons = jQuery.parseJSON( fontAwesomeJSON ), |
||
| 1723 | selectValue, |
||
| 1724 | selectWooOptions = { |
||
| 1725 | data: [], |
||
| 1726 | escapeMarkup: function( markup ) { |
||
| 1727 | return markup; |
||
| 1728 | }, |
||
| 1729 | templateResult: function( val ) { |
||
| 1730 | return '<i class="fa fa-lg fa-' + val.id + '" aria-hidden="true"></i>' + ' ' + val.text; |
||
| 1731 | }, |
||
| 1732 | templateSelection: function( val ) { |
||
| 1733 | return '<i class="fa fa-lg fa-' + val.id + '" aria-hidden="true"></i>' + ' ' + val.text; |
||
| 1734 | } |
||
| 1735 | }, |
||
| 1736 | select; |
||
| 1737 | |||
| 1738 | _.each( icons.icons, function( icon ) { |
||
| 1739 | selectWooOptions.data.push({ |
||
| 1740 | id: icon.id, |
||
| 1741 | text: icon.name |
||
| 1742 | }); |
||
| 1743 | }); |
||
| 1744 | |||
| 1745 | select = jQuery( element ).selectWoo( selectWooOptions ); |
||
| 1746 | |||
| 1747 | select.on( 'change', function() { |
||
| 1748 | selectValue = jQuery( this ).val(); |
||
| 1749 | control.setting.set( selectValue ); |
||
| 1750 | }); |
||
| 1751 | select.val( control.setting._value ).trigger( 'change' ); |
||
| 1752 | } |
||
| 1753 | }); |
||
| 1754 | /* global kirkiControlLoader */ |
||
| 1755 | wp.customize.controlConstructor['kirki-image'] = wp.customize.Control.extend({ |
||
| 1756 | |||
| 1757 | // When we're finished loading continue processing |
||
| 1758 | ready: function() { |
||
| 1759 | |||
| 1760 | 'use strict'; |
||
| 1761 | |||
| 1762 | var control = this; |
||
| 1763 | |||
| 1764 | // Init the control. |
||
| 1765 | if ( ! _.isUndefined( window.kirkiControlLoader ) && _.isFunction( kirkiControlLoader ) ) { |
||
| 1766 | kirkiControlLoader( control ); |
||
| 1767 | } else { |
||
| 1768 | control.initKirkiControl(); |
||
| 1769 | } |
||
| 1770 | }, |
||
| 1771 | |||
| 1772 | View Code Duplication | initKirkiControl: function() { |
|
| 1773 | |||
| 1774 | var control = this, |
||
| 1775 | value = control.getValue(), |
||
| 1776 | saveAs = ( ! _.isUndefined( control.params.choices ) && ! _.isUndefined( control.params.choices.save_as ) ) ? control.params.choices.save_as : 'url', |
||
| 1777 | preview = control.container.find( '.placeholder, .thumbnail' ), |
||
| 1778 | previewImage = ( 'array' === saveAs ) ? value.url : value, |
||
| 1779 | removeButton = control.container.find( '.image-upload-remove-button' ), |
||
| 1780 | defaultButton = control.container.find( '.image-default-button' ); |
||
| 1781 | |||
| 1782 | control.container.find( '.kirki-controls-loading-spinner' ).hide(); |
||
| 1783 | |||
| 1784 | // Tweaks for save_as = id. |
||
| 1785 | if ( ( 'id' === saveAs || 'ID' === saveAs ) && '' !== value ) { |
||
| 1786 | wp.media.attachment( value ).fetch().then( function() { |
||
| 1787 | setTimeout( function() { |
||
| 1788 | var url = wp.media.attachment( value ).get( 'url' ); |
||
| 1789 | preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '<img src="' + url + '" alt="" />' ); |
||
| 1790 | }, 700 ); |
||
| 1791 | } ); |
||
| 1792 | } |
||
| 1793 | |||
| 1794 | // If value is not empty, hide the "default" button. |
||
| 1795 | if ( ( 'url' === saveAs && '' !== value ) || ( 'array' === saveAs && ! _.isUndefined( value.url ) && '' !== value.url ) ) { |
||
| 1796 | control.container.find( 'image-default-button' ).hide(); |
||
| 1797 | } |
||
| 1798 | |||
| 1799 | // If value is empty, hide the "remove" button. |
||
| 1800 | if ( ( 'url' === saveAs && '' === value ) || ( 'array' === saveAs && ( _.isUndefined( value.url ) || '' === value.url ) ) ) { |
||
| 1801 | removeButton.hide(); |
||
| 1802 | } |
||
| 1803 | |||
| 1804 | // If value is default, hide the default button. |
||
| 1805 | if ( value === control.params['default'] ) { |
||
| 1806 | control.container.find( 'image-default-button' ).hide(); |
||
| 1807 | } |
||
| 1808 | |||
| 1809 | if ( '' !== previewImage ) { |
||
| 1810 | preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '<img src="' + previewImage + '" alt="" />' ); |
||
| 1811 | } |
||
| 1812 | |||
| 1813 | control.container.on( 'click', '.image-upload-button', function( e ) { |
||
| 1814 | var image = wp.media({ multiple: false }).open().on( 'select', function() { |
||
| 1815 | |||
| 1816 | // This will return the selected image from the Media Uploader, the result is an object. |
||
| 1817 | var uploadedImage = image.state().get( 'selection' ).first(), |
||
| 1818 | previewImage = uploadedImage.toJSON().sizes.full.url; |
||
| 1819 | |||
| 1820 | if ( ! _.isUndefined( uploadedImage.toJSON().sizes.medium ) ) { |
||
| 1821 | previewImage = uploadedImage.toJSON().sizes.medium.url; |
||
| 1822 | } else if ( ! _.isUndefined( uploadedImage.toJSON().sizes.thumbnail ) ) { |
||
| 1823 | previewImage = uploadedImage.toJSON().sizes.thumbnail.url; |
||
| 1824 | } |
||
| 1825 | |||
| 1826 | if ( 'array' === saveAs ) { |
||
| 1827 | control.saveValue( 'id', uploadedImage.toJSON().id ); |
||
| 1828 | control.saveValue( 'url', uploadedImage.toJSON().sizes.full.url ); |
||
| 1829 | control.saveValue( 'width', uploadedImage.toJSON().width ); |
||
| 1830 | control.saveValue( 'height', uploadedImage.toJSON().height ); |
||
| 1831 | } else if ( 'id' === saveAs ) { |
||
| 1832 | control.saveValue( 'id', uploadedImage.toJSON().id ); |
||
| 1833 | } else { |
||
| 1834 | control.saveValue( 'url', uploadedImage.toJSON().sizes.full.url ); |
||
| 1835 | } |
||
| 1836 | |||
| 1837 | if ( preview.length ) { |
||
| 1838 | preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '<img src="' + previewImage + '" alt="" />' ); |
||
| 1839 | } |
||
| 1840 | if ( removeButton.length ) { |
||
| 1841 | removeButton.show(); |
||
| 1842 | defaultButton.hide(); |
||
| 1843 | } |
||
| 1844 | }); |
||
| 1845 | |||
| 1846 | e.preventDefault(); |
||
| 1847 | }); |
||
| 1848 | |||
| 1849 | control.container.on( 'click', '.image-upload-remove-button', function( e ) { |
||
| 1850 | |||
| 1851 | var preview, |
||
| 1852 | removeButton, |
||
| 1853 | defaultButton; |
||
| 1854 | |||
| 1855 | e.preventDefault(); |
||
| 1856 | |||
| 1857 | control.saveValue( 'id', '' ); |
||
| 1858 | control.saveValue( 'url', '' ); |
||
| 1859 | control.saveValue( 'width', '' ); |
||
| 1860 | control.saveValue( 'height', '' ); |
||
| 1861 | |||
| 1862 | preview = control.container.find( '.placeholder, .thumbnail' ); |
||
| 1863 | removeButton = control.container.find( '.image-upload-remove-button' ); |
||
| 1864 | defaultButton = control.container.find( '.image-default-button' ); |
||
| 1865 | |||
| 1866 | if ( preview.length ) { |
||
| 1867 | preview.removeClass().addClass( 'placeholder' ).html( 'No file selected' ); |
||
| 1868 | } |
||
| 1869 | if ( removeButton.length ) { |
||
| 1870 | removeButton.hide(); |
||
| 1871 | if ( jQuery( defaultButton ).hasClass( 'button' ) ) { |
||
| 1872 | defaultButton.show(); |
||
| 1873 | } |
||
| 1874 | } |
||
| 1875 | }); |
||
| 1876 | |||
| 1877 | control.container.on( 'click', '.image-default-button', function( e ) { |
||
| 1878 | |||
| 1879 | var preview, |
||
| 1880 | removeButton, |
||
| 1881 | defaultButton; |
||
| 1882 | |||
| 1883 | e.preventDefault(); |
||
| 1884 | |||
| 1885 | control.saveValue( 'url', control.params['default'] ); |
||
| 1886 | |||
| 1887 | preview = control.container.find( '.placeholder, .thumbnail' ); |
||
| 1888 | removeButton = control.container.find( '.image-upload-remove-button' ); |
||
| 1889 | defaultButton = control.container.find( '.image-default-button' ); |
||
| 1890 | |||
| 1891 | if ( preview.length ) { |
||
| 1892 | preview.removeClass().addClass( 'thumbnail thumbnail-image' ).html( '<img src="' + control.params['default'] + '" alt="" />' ); |
||
| 1893 | } |
||
| 1894 | if ( removeButton.length ) { |
||
| 1895 | removeButton.show(); |
||
| 1896 | defaultButton.hide(); |
||
| 1897 | } |
||
| 1898 | }); |
||
| 1899 | }, |
||
| 1900 | |||
| 1901 | /** |
||
| 1902 | * Gets the value. |
||
| 1903 | */ |
||
| 1904 | getValue: function() { |
||
| 1905 | var control = this, |
||
| 1906 | value = control.setting._value, |
||
| 1907 | saveAs = ( ! _.isUndefined( control.params.choices ) && ! _.isUndefined( control.params.choices.save_as ) ) ? control.params.choices.save_as : 'url'; |
||
| 1908 | |||
| 1909 | if ( 'array' === saveAs && _.isString( value ) ) { |
||
| 1910 | value = { |
||
| 1911 | url: value |
||
| 1912 | }; |
||
| 1913 | } |
||
| 1914 | return value; |
||
| 1915 | }, |
||
| 1916 | |||
| 1917 | /** |
||
| 1918 | * Saves the value. |
||
| 1919 | */ |
||
| 1920 | saveValue: function( property, value ) { |
||
| 1921 | var control = this, |
||
| 1922 | valueOld = control.setting._value, |
||
| 1923 | saveAs = ( ! _.isUndefined( control.params.choices ) && ! _.isUndefined( control.params.choices.save_as ) ) ? control.params.choices.save_as : 'url'; |
||
| 1924 | |||
| 1925 | if ( 'array' === saveAs ) { |
||
| 1926 | if ( _.isString( valueOld ) ) { |
||
| 1927 | valueOld = {}; |
||
| 1928 | } |
||
| 1929 | valueOld[ property ] = value; |
||
| 1930 | control.setting.set( valueOld ); |
||
| 1931 | control.container.find( 'button' ).trigger( 'change' ); |
||
| 1932 | return; |
||
| 1933 | } |
||
| 1934 | control.setting.set( value ); |
||
| 1935 | control.container.find( 'button' ).trigger( 'change' ); |
||
| 1936 | } |
||
| 1937 | }); |
||
| 1938 | wp.customize.controlConstructor['kirki-multicheck'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 1939 | |||
| 1940 | initKirkiControl: function() { |
||
| 1941 | |||
| 1942 | var control = this; |
||
| 1943 | |||
| 1944 | // Save the value |
||
| 1945 | control.container.on( 'change', 'input', function() { |
||
| 1946 | var value = [], |
||
| 1947 | i = 0; |
||
| 1948 | |||
| 1949 | // Build the value as an object using the sub-values from individual checkboxes. |
||
| 1950 | jQuery.each( control.params.choices, function( key ) { |
||
| 1951 | if ( control.container.find( 'input[value="' + key + '"]' ).is( ':checked' ) ) { |
||
| 1952 | value[ i ] = key; |
||
| 1953 | i++; |
||
| 1954 | } |
||
| 1955 | }); |
||
| 1956 | |||
| 1957 | // Update the value in the customizer. |
||
| 1958 | control.setting.set( value ); |
||
| 1959 | }); |
||
| 1960 | } |
||
| 1961 | }); |
||
| 1962 | /* global kirkiControlLoader */ |
||
| 1963 | wp.customize.controlConstructor['kirki-multicolor'] = wp.customize.Control.extend({ |
||
| 1964 | |||
| 1965 | // When we're finished loading continue processing |
||
| 1966 | ready: function() { |
||
| 1967 | |||
| 1968 | 'use strict'; |
||
| 1969 | |||
| 1970 | var control = this; |
||
| 1971 | |||
| 1972 | // Init the control. |
||
| 1973 | if ( ! _.isUndefined( window.kirkiControlLoader ) && _.isFunction( kirkiControlLoader ) ) { |
||
| 1974 | kirkiControlLoader( control ); |
||
| 1975 | } else { |
||
| 1976 | control.initKirkiControl(); |
||
| 1977 | } |
||
| 1978 | }, |
||
| 1979 | |||
| 1980 | initKirkiControl: function() { |
||
| 1981 | |||
| 1982 | 'use strict'; |
||
| 1983 | |||
| 1984 | var control = this, |
||
| 1985 | colors = control.params.choices, |
||
| 1986 | keys = Object.keys( colors ), |
||
| 1987 | value = this.params.value, |
||
| 1988 | i = 0; |
||
| 1989 | |||
| 1990 | // Proxy function that handles changing the individual colors |
||
| 1991 | function kirkiMulticolorChangeHandler( control, value, subSetting ) { |
||
| 1992 | |||
| 1993 | var picker = control.container.find( '.multicolor-index-' + subSetting ), |
||
| 1994 | args = { |
||
| 1995 | change: function() { |
||
| 1996 | |||
| 1997 | // Color controls require a small delay. |
||
| 1998 | setTimeout( function() { |
||
| 1999 | |||
| 2000 | // Set the value. |
||
| 2001 | control.saveValue( subSetting, picker.val() ); |
||
| 2002 | |||
| 2003 | // Trigger the change. |
||
| 2004 | control.container.find( '.multicolor-index-' + subSetting ).trigger( 'change' ); |
||
| 2005 | }, 100 ); |
||
| 2006 | } |
||
| 2007 | }; |
||
| 2008 | |||
| 2009 | if ( _.isObject( colors.irisArgs ) ) { |
||
| 2010 | _.each( colors.irisArgs, function( irisValue, irisKey ) { |
||
| 2011 | args[ irisKey ] = irisValue; |
||
| 2012 | }); |
||
| 2013 | } |
||
| 2014 | |||
| 2015 | // Did we change the value? |
||
| 2016 | picker.wpColorPicker( args ); |
||
| 2017 | } |
||
| 2018 | |||
| 2019 | // Colors loop |
||
| 2020 | while ( i < Object.keys( colors ).length ) { |
||
| 2021 | kirkiMulticolorChangeHandler( this, value, keys[ i ] ); |
||
| 2022 | i++; |
||
| 2023 | } |
||
| 2024 | }, |
||
| 2025 | |||
| 2026 | /** |
||
| 2027 | * Saves the value. |
||
| 2028 | */ |
||
| 2029 | saveValue: function( property, value ) { |
||
| 2030 | |||
| 2031 | var control = this, |
||
| 2032 | input = control.container.find( '.multicolor-hidden-value' ), |
||
| 2033 | val = control.setting._value; |
||
| 2034 | |||
| 2035 | val[ property ] = value; |
||
| 2036 | |||
| 2037 | jQuery( input ).attr( 'value', JSON.stringify( val ) ).trigger( 'change' ); |
||
| 2038 | control.setting.set( val ); |
||
| 2039 | } |
||
| 2040 | }); |
||
| 2041 | wp.customize.controlConstructor['kirki-number'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 2042 | |||
| 2043 | initKirkiControl: function() { |
||
| 2044 | |||
| 2045 | var control = this, |
||
| 2046 | value = control.setting._value, |
||
| 2047 | html = '', |
||
| 2048 | input, |
||
| 2049 | up, |
||
| 2050 | down; |
||
| 2051 | |||
| 2052 | // Make sure we use default values if none are define for some arguments. |
||
| 2053 | control.params.choices = _.defaults( control.params.choices, { |
||
| 2054 | min: 0, |
||
| 2055 | max: 100, |
||
| 2056 | step: 1 |
||
| 2057 | } ); |
||
| 2058 | |||
| 2059 | // Make sure we have a valid value. |
||
| 2060 | if ( isNaN( value ) || '' === value ) { |
||
| 2061 | value = ( 0 > control.params.choices.min && 0 < control.params.choices.max ) ? 0 : control.params.choices.min; |
||
| 2062 | } |
||
| 2063 | value = parseFloat( value ); |
||
| 2064 | |||
| 2065 | // If step is 'any', set to 0.001. |
||
| 2066 | control.params.choices.step = ( 'any' === control.params.choices.step ) ? 0.001 : control.params.choices.step; |
||
| 2067 | |||
| 2068 | // Make sure choices are properly formtted as numbers. |
||
| 2069 | control.params.choices.min = parseFloat( control.params.choices.min ); |
||
| 2070 | control.params.choices.max = parseFloat( control.params.choices.max ); |
||
| 2071 | control.params.choices.step = parseFloat( control.params.choices.step ); |
||
| 2072 | |||
| 2073 | // Build the HTML for the control. |
||
| 2074 | html += '<label>'; |
||
| 2075 | if ( control.params.label ) { |
||
| 2076 | html += '<span class="customize-control-title">' + control.params.label + '</span>'; |
||
| 2077 | } |
||
| 2078 | if ( control.params.description ) { |
||
| 2079 | html += '<span class="description customize-control-description">' + control.params.description + '</span>'; |
||
| 2080 | } |
||
| 2081 | html += '<div class="customize-control-content">'; |
||
| 2082 | html += '<input ' + control.params.inputAttrs + ' type="text" ' + control.params.link + ' value="' + value + '" />'; |
||
| 2083 | html += '<div class="quantity button minus">-</div>'; |
||
| 2084 | html += '<div class="quantity button plus">+</div>'; |
||
| 2085 | html += '</div>'; |
||
| 2086 | html += '</label>'; |
||
| 2087 | |||
| 2088 | control.container.html( html ); |
||
| 2089 | |||
| 2090 | input = control.container.find( 'input' ); |
||
| 2091 | up = control.container.find( '.plus' ); |
||
| 2092 | down = control.container.find( '.minus' ); |
||
| 2093 | |||
| 2094 | up.click( function() { |
||
| 2095 | var oldVal = parseFloat( input.val() ), |
||
| 2096 | newVal; |
||
| 2097 | |||
| 2098 | newVal = ( oldVal >= control.params.choices.max ) ? oldVal : oldVal + control.params.choices.step; |
||
| 2099 | |||
| 2100 | input.val( newVal ); |
||
| 2101 | input.trigger( 'change' ); |
||
| 2102 | } ); |
||
| 2103 | |||
| 2104 | down.click( function() { |
||
| 2105 | var oldVal = parseFloat( input.val() ), |
||
| 2106 | newVal; |
||
| 2107 | |||
| 2108 | newVal = ( oldVal <= control.params.choices.min ) ? oldVal : oldVal - control.params.choices.step; |
||
| 2109 | |||
| 2110 | input.val( newVal ); |
||
| 2111 | input.trigger( 'change' ); |
||
| 2112 | } ); |
||
| 2113 | |||
| 2114 | this.container.on( 'change keyup paste click', 'input', function() { |
||
| 2115 | control.setting.set( jQuery( this ).val() ); |
||
| 2116 | }); |
||
| 2117 | } |
||
| 2118 | }); |
||
| 2119 | wp.customize.controlConstructor['kirki-palette'] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 2120 | /* global kirkiSetSettingValue */ |
||
| 2121 | wp.customize.controlConstructor['kirki-preset'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 2122 | |||
| 2123 | initKirkiControl: function() { |
||
| 2124 | |||
| 2125 | var control = this, |
||
| 2126 | selectValue; |
||
| 2127 | |||
| 2128 | // Trigger a change |
||
| 2129 | this.container.on( 'change', 'select', function() { |
||
| 2130 | |||
| 2131 | // Get the control's value |
||
| 2132 | selectValue = jQuery( this ).val(); |
||
| 2133 | |||
| 2134 | // Update the value using the customizer API and trigger the "save" button |
||
| 2135 | control.setting.set( selectValue ); |
||
| 2136 | |||
| 2137 | // We have to get the choices of this control |
||
| 2138 | // and then start parsing them to see what we have to do for each of the choices. |
||
| 2139 | jQuery.each( control.params.choices, function( key, value ) { |
||
| 2140 | |||
| 2141 | // If the current value of the control is the key of the choice, |
||
| 2142 | // then we can continue processing, Otherwise there's no reason to do anything. |
||
| 2143 | if ( selectValue === key ) { |
||
| 2144 | |||
| 2145 | // Each choice has an array of settings defined in it. |
||
| 2146 | // We'll have to loop through them all and apply the changes needed to them. |
||
| 2147 | jQuery.each( value.settings, function( presetSetting, presetSettingValue ) { |
||
| 2148 | kirkiSetSettingValue.set( presetSetting, presetSettingValue ); |
||
| 2149 | }); |
||
| 2150 | } |
||
| 2151 | }); |
||
| 2152 | wp.customize.previewer.refresh(); |
||
| 2153 | }); |
||
| 2154 | } |
||
| 2155 | }); |
||
| 2156 | wp.customize.controlConstructor['kirki-radio-buttonset'] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 2157 | wp.customize.controlConstructor['kirki-radio-image'] = wp.customize.kirkiDynamicControl.extend({}); |
||
| 2158 | /* global kirkiControlLoader */ |
||
| 2159 | View Code Duplication | var RepeaterRow = function( rowIndex, container, label, control ) { |
|
| 2160 | |||
| 2161 | 'use strict'; |
||
| 2162 | |||
| 2163 | var self = this; |
||
| 2164 | this.rowIndex = rowIndex; |
||
| 2165 | this.container = container; |
||
| 2166 | this.label = label; |
||
| 2167 | this.header = this.container.find( '.repeater-row-header' ), |
||
| 2168 | |||
| 2169 | this.header.on( 'click', function() { |
||
| 2170 | self.toggleMinimize(); |
||
| 2171 | }); |
||
| 2172 | |||
| 2173 | this.container.on( 'click', '.repeater-row-remove', function() { |
||
| 2174 | self.remove(); |
||
| 2175 | }); |
||
| 2176 | |||
| 2177 | this.header.on( 'mousedown', function() { |
||
| 2178 | self.container.trigger( 'row:start-dragging' ); |
||
| 2179 | }); |
||
| 2180 | |||
| 2181 | this.container.on( 'keyup change', 'input, select, textarea', function( e ) { |
||
| 2182 | self.container.trigger( 'row:update', [ self.rowIndex, jQuery( e.target ).data( 'field' ), e.target ] ); |
||
| 2183 | }); |
||
| 2184 | |||
| 2185 | this.setRowIndex = function( rowIndex ) { |
||
| 2186 | this.rowIndex = rowIndex; |
||
| 2187 | this.container.attr( 'data-row', rowIndex ); |
||
| 2188 | this.container.data( 'row', rowIndex ); |
||
| 2189 | this.updateLabel(); |
||
| 2190 | }; |
||
| 2191 | |||
| 2192 | this.toggleMinimize = function() { |
||
| 2193 | |||
| 2194 | // Store the previous state. |
||
| 2195 | this.container.toggleClass( 'minimized' ); |
||
| 2196 | this.header.find( '.dashicons' ).toggleClass( 'dashicons-arrow-up' ).toggleClass( 'dashicons-arrow-down' ); |
||
| 2197 | }; |
||
| 2198 | |||
| 2199 | this.remove = function() { |
||
| 2200 | this.container.slideUp( 300, function() { |
||
| 2201 | jQuery( this ).detach(); |
||
| 2202 | }); |
||
| 2203 | this.container.trigger( 'row:remove', [ this.rowIndex ] ); |
||
| 2204 | }; |
||
| 2205 | |||
| 2206 | this.updateLabel = function() { |
||
| 2207 | var rowLabelField, |
||
| 2208 | rowLabel, |
||
| 2209 | rowLabelSelector; |
||
| 2210 | |||
| 2211 | if ( 'field' === this.label.type ) { |
||
| 2212 | rowLabelField = this.container.find( '.repeater-field [data-field="' + this.label.field + '"]' ); |
||
| 2213 | if ( _.isFunction( rowLabelField.val ) ) { |
||
| 2214 | rowLabel = rowLabelField.val(); |
||
| 2215 | if ( '' !== rowLabel ) { |
||
| 2216 | if ( ! _.isUndefined( control.params.fields[ this.label.field ] ) ) { |
||
| 2217 | if ( ! _.isUndefined( control.params.fields[ this.label.field ].type ) ) { |
||
| 2218 | if ( 'select' === control.params.fields[ this.label.field ].type ) { |
||
| 2219 | if ( ! _.isUndefined( control.params.fields[ this.label.field ].choices ) && ! _.isUndefined( control.params.fields[ this.label.field ].choices[ rowLabelField.val() ] ) ) { |
||
| 2220 | rowLabel = control.params.fields[ this.label.field ].choices[ rowLabelField.val() ]; |
||
| 2221 | } |
||
| 2222 | } else if ( 'radio' === control.params.fields[ this.label.field ].type || 'radio-image' === control.params.fields[ this.label.field ].type ) { |
||
| 2223 | rowLabelSelector = control.selector + ' [data-row="' + this.rowIndex + '"] .repeater-field [data-field="' + this.label.field + '"]:checked'; |
||
| 2224 | rowLabel = jQuery( rowLabelSelector ).val(); |
||
| 2225 | } |
||
| 2226 | } |
||
| 2227 | } |
||
| 2228 | this.header.find( '.repeater-row-label' ).text( rowLabel ); |
||
| 2229 | return; |
||
| 2230 | } |
||
| 2231 | } |
||
| 2232 | } |
||
| 2233 | this.header.find( '.repeater-row-label' ).text( this.label.value + ' ' + ( this.rowIndex + 1 ) ); |
||
| 2234 | }; |
||
| 2235 | this.updateLabel(); |
||
| 2236 | }; |
||
| 2237 | |||
| 2238 | wp.customize.controlConstructor.repeater = wp.customize.Control.extend({ |
||
| 2239 | |||
| 2240 | // When we're finished loading continue processing |
||
| 2241 | ready: function() { |
||
| 2242 | |||
| 2243 | 'use strict'; |
||
| 2244 | |||
| 2245 | var control = this; |
||
| 2246 | |||
| 2247 | // Init the control. |
||
| 2248 | if ( ! _.isUndefined( window.kirkiControlLoader ) && _.isFunction( kirkiControlLoader ) ) { |
||
| 2249 | kirkiControlLoader( control ); |
||
| 2250 | } else { |
||
| 2251 | control.initKirkiControl(); |
||
| 2252 | } |
||
| 2253 | }, |
||
| 2254 | |||
| 2255 | View Code Duplication | initKirkiControl: function() { |
|
| 2256 | |||
| 2257 | 'use strict'; |
||
| 2258 | |||
| 2259 | var control = this, |
||
| 2260 | limit, |
||
| 2261 | theNewRow; |
||
| 2262 | |||
| 2263 | // The current value set in Control Class (set in Kirki_Customize_Repeater_Control::to_json() function) |
||
| 2264 | var settingValue = this.params.value; |
||
| 2265 | |||
| 2266 | control.container.find( '.kirki-controls-loading-spinner' ).hide(); |
||
| 2267 | |||
| 2268 | // The hidden field that keeps the data saved (though we never update it) |
||
| 2269 | this.settingField = this.container.find( '[data-customize-setting-link]' ).first(); |
||
| 2270 | |||
| 2271 | // Set the field value for the first time, we'll fill it up later |
||
| 2272 | this.setValue( [], false ); |
||
| 2273 | |||
| 2274 | // The DIV that holds all the rows |
||
| 2275 | this.repeaterFieldsContainer = this.container.find( '.repeater-fields' ).first(); |
||
| 2276 | |||
| 2277 | // Set number of rows to 0 |
||
| 2278 | this.currentIndex = 0; |
||
| 2279 | |||
| 2280 | // Save the rows objects |
||
| 2281 | this.rows = []; |
||
| 2282 | |||
| 2283 | // Default limit choice |
||
| 2284 | limit = false; |
||
| 2285 | if ( ! _.isUndefined( this.params.choices.limit ) ) { |
||
| 2286 | limit = ( 0 >= this.params.choices.limit ) ? false : parseInt( this.params.choices.limit, 10 ); |
||
| 2287 | } |
||
| 2288 | |||
| 2289 | this.container.on( 'click', 'button.repeater-add', function( e ) { |
||
| 2290 | e.preventDefault(); |
||
| 2291 | if ( ! limit || control.currentIndex < limit ) { |
||
| 2292 | theNewRow = control.addRow(); |
||
| 2293 | theNewRow.toggleMinimize(); |
||
| 2294 | control.initColorPicker(); |
||
| 2295 | control.initSelect( theNewRow ); |
||
| 2296 | } else { |
||
| 2297 | jQuery( control.selector + ' .limit' ).addClass( 'highlight' ); |
||
| 2298 | } |
||
| 2299 | }); |
||
| 2300 | |||
| 2301 | this.container.on( 'click', '.repeater-row-remove', function() { |
||
| 2302 | control.currentIndex--; |
||
| 2303 | if ( ! limit || control.currentIndex < limit ) { |
||
| 2304 | jQuery( control.selector + ' .limit' ).removeClass( 'highlight' ); |
||
| 2305 | } |
||
| 2306 | }); |
||
| 2307 | |||
| 2308 | this.container.on( 'click keypress', '.repeater-field-image .upload-button,.repeater-field-cropped_image .upload-button,.repeater-field-upload .upload-button', function( e ) { |
||
| 2309 | e.preventDefault(); |
||
| 2310 | control.$thisButton = jQuery( this ); |
||
| 2311 | control.openFrame( e ); |
||
| 2312 | }); |
||
| 2313 | |||
| 2314 | this.container.on( 'click keypress', '.repeater-field-image .remove-button,.repeater-field-cropped_image .remove-button', function( e ) { |
||
| 2315 | e.preventDefault(); |
||
| 2316 | control.$thisButton = jQuery( this ); |
||
| 2317 | control.removeImage( e ); |
||
| 2318 | }); |
||
| 2319 | |||
| 2320 | this.container.on( 'click keypress', '.repeater-field-upload .remove-button', function( e ) { |
||
| 2321 | e.preventDefault(); |
||
| 2322 | control.$thisButton = jQuery( this ); |
||
| 2323 | control.removeFile( e ); |
||
| 2324 | }); |
||
| 2325 | |||
| 2326 | /** |
||
| 2327 | * Function that loads the Mustache template |
||
| 2328 | */ |
||
| 2329 | this.repeaterTemplate = _.memoize( function() { |
||
| 2330 | var compiled, |
||
| 2331 | /* |
||
| 2332 | * Underscore's default ERB-style templates are incompatible with PHP |
||
| 2333 | * when asp_tags is enabled, so WordPress uses Mustache-inspired templating syntax. |
||
| 2334 | * |
||
| 2335 | * @see trac ticket #22344. |
||
| 2336 | */ |
||
| 2337 | options = { |
||
| 2338 | evaluate: /<#([\s\S]+?)#>/g, |
||
| 2339 | interpolate: /\{\{\{([\s\S]+?)\}\}\}/g, |
||
| 2340 | escape: /\{\{([^\}]+?)\}\}(?!\})/g, |
||
| 2341 | variable: 'data' |
||
| 2342 | }; |
||
| 2343 | |||
| 2344 | return function( data ) { |
||
| 2345 | compiled = _.template( control.container.find( '.customize-control-repeater-content' ).first().html(), null, options ); |
||
| 2346 | return compiled( data ); |
||
| 2347 | }; |
||
| 2348 | }); |
||
| 2349 | |||
| 2350 | // When we load the control, the fields have not been filled up |
||
| 2351 | // This is the first time that we create all the rows |
||
| 2352 | if ( settingValue.length ) { |
||
| 2353 | _.each( settingValue, function( subValue ) { |
||
| 2354 | theNewRow = control.addRow( subValue ); |
||
| 2355 | control.initColorPicker(); |
||
| 2356 | control.initSelect( theNewRow, subValue ); |
||
| 2357 | }); |
||
| 2358 | } |
||
| 2359 | |||
| 2360 | // Once we have displayed the rows, we cleanup the values |
||
| 2361 | this.setValue( settingValue, true, true ); |
||
| 2362 | |||
| 2363 | this.repeaterFieldsContainer.sortable({ |
||
| 2364 | handle: '.repeater-row-header', |
||
| 2365 | update: function() { |
||
| 2366 | control.sort(); |
||
| 2367 | } |
||
| 2368 | }); |
||
| 2369 | |||
| 2370 | }, |
||
| 2371 | |||
| 2372 | /** |
||
| 2373 | * Open the media modal. |
||
| 2374 | */ |
||
| 2375 | openFrame: function( event ) { |
||
| 2376 | |||
| 2377 | 'use strict'; |
||
| 2378 | |||
| 2379 | if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { |
||
| 2380 | return; |
||
| 2381 | } |
||
| 2382 | |||
| 2383 | if ( this.$thisButton.closest( '.repeater-field' ).hasClass( 'repeater-field-cropped_image' ) ) { |
||
| 2384 | this.initCropperFrame(); |
||
| 2385 | } else { |
||
| 2386 | this.initFrame(); |
||
| 2387 | } |
||
| 2388 | |||
| 2389 | this.frame.open(); |
||
| 2390 | }, |
||
| 2391 | |||
| 2392 | initFrame: function() { |
||
| 2393 | |||
| 2394 | 'use strict'; |
||
| 2395 | |||
| 2396 | var libMediaType = this.getMimeType(); |
||
| 2397 | |||
| 2398 | this.frame = wp.media({ |
||
| 2399 | states: [ |
||
| 2400 | new wp.media.controller.Library({ |
||
| 2401 | library: wp.media.query({ type: libMediaType }), |
||
| 2402 | multiple: false, |
||
| 2403 | date: false |
||
| 2404 | }) |
||
| 2405 | ] |
||
| 2406 | }); |
||
| 2407 | |||
| 2408 | // When a file is selected, run a callback. |
||
| 2409 | this.frame.on( 'select', this.onSelect, this ); |
||
| 2410 | }, |
||
| 2411 | /** |
||
| 2412 | * Create a media modal select frame, and store it so the instance can be reused when needed. |
||
| 2413 | * This is mostly a copy/paste of Core api.CroppedImageControl in /wp-admin/js/customize-control.js |
||
| 2414 | */ |
||
| 2415 | initCropperFrame: function() { |
||
| 2416 | |||
| 2417 | 'use strict'; |
||
| 2418 | |||
| 2419 | // We get the field id from which this was called |
||
| 2420 | var currentFieldId = this.$thisButton.siblings( 'input.hidden-field' ).attr( 'data-field' ), |
||
| 2421 | attrs = [ 'width', 'height', 'flex_width', 'flex_height' ], // A list of attributes to look for |
||
| 2422 | libMediaType = this.getMimeType(); |
||
| 2423 | |||
| 2424 | // Make sure we got it |
||
| 2425 | if ( _.isString( currentFieldId ) && '' !== currentFieldId ) { |
||
| 2426 | |||
| 2427 | // Make fields is defined and only do the hack for cropped_image |
||
| 2428 | if ( _.isObject( this.params.fields[ currentFieldId ] ) && 'cropped_image' === this.params.fields[ currentFieldId ].type ) { |
||
| 2429 | |||
| 2430 | //Iterate over the list of attributes |
||
| 2431 | attrs.forEach( function( el ) { |
||
| 2432 | |||
| 2433 | // If the attribute exists in the field |
||
| 2434 | if ( ! _.isUndefined( this.params.fields[ currentFieldId ][ el ] ) ) { |
||
| 2435 | |||
| 2436 | // Set the attribute in the main object |
||
| 2437 | this.params[ el ] = this.params.fields[ currentFieldId ][ el ]; |
||
| 2438 | } |
||
| 2439 | }.bind( this ) ); |
||
| 2440 | } |
||
| 2441 | } |
||
| 2442 | |||
| 2443 | this.frame = wp.media({ |
||
| 2444 | button: { |
||
| 2445 | text: 'Select and Crop', |
||
| 2446 | close: false |
||
| 2447 | }, |
||
| 2448 | states: [ |
||
| 2449 | new wp.media.controller.Library({ |
||
| 2450 | library: wp.media.query({ type: libMediaType }), |
||
| 2451 | multiple: false, |
||
| 2452 | date: false, |
||
| 2453 | suggestedWidth: this.params.width, |
||
| 2454 | suggestedHeight: this.params.height |
||
| 2455 | }), |
||
| 2456 | new wp.media.controller.CustomizeImageCropper({ |
||
| 2457 | imgSelectOptions: this.calculateImageSelectOptions, |
||
| 2458 | control: this |
||
| 2459 | }) |
||
| 2460 | ] |
||
| 2461 | }); |
||
| 2462 | |||
| 2463 | this.frame.on( 'select', this.onSelectForCrop, this ); |
||
| 2464 | this.frame.on( 'cropped', this.onCropped, this ); |
||
| 2465 | this.frame.on( 'skippedcrop', this.onSkippedCrop, this ); |
||
| 2466 | |||
| 2467 | }, |
||
| 2468 | |||
| 2469 | onSelect: function() { |
||
| 2470 | |||
| 2471 | 'use strict'; |
||
| 2472 | |||
| 2473 | var attachment = this.frame.state().get( 'selection' ).first().toJSON(); |
||
| 2474 | |||
| 2475 | if ( this.$thisButton.closest( '.repeater-field' ).hasClass( 'repeater-field-upload' ) ) { |
||
| 2476 | this.setFileInRepeaterField( attachment ); |
||
| 2477 | } else { |
||
| 2478 | this.setImageInRepeaterField( attachment ); |
||
| 2479 | } |
||
| 2480 | }, |
||
| 2481 | |||
| 2482 | /** |
||
| 2483 | * After an image is selected in the media modal, switch to the cropper |
||
| 2484 | * state if the image isn't the right size. |
||
| 2485 | */ |
||
| 2486 | |||
| 2487 | onSelectForCrop: function() { |
||
| 2488 | |||
| 2489 | 'use strict'; |
||
| 2490 | |||
| 2491 | var attachment = this.frame.state().get( 'selection' ).first().toJSON(); |
||
| 2492 | |||
| 2493 | if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) { |
||
| 2494 | this.setImageInRepeaterField( attachment ); |
||
| 2495 | } else { |
||
| 2496 | this.frame.setState( 'cropper' ); |
||
| 2497 | } |
||
| 2498 | }, |
||
| 2499 | |||
| 2500 | /** |
||
| 2501 | * After the image has been cropped, apply the cropped image data to the setting. |
||
| 2502 | * |
||
| 2503 | * @param {object} croppedImage Cropped attachment data. |
||
| 2504 | */ |
||
| 2505 | onCropped: function( croppedImage ) { |
||
| 2506 | |||
| 2507 | 'use strict'; |
||
| 2508 | |||
| 2509 | this.setImageInRepeaterField( croppedImage ); |
||
| 2510 | |||
| 2511 | }, |
||
| 2512 | |||
| 2513 | /** |
||
| 2514 | * Returns a set of options, computed from the attached image data and |
||
| 2515 | * control-specific data, to be fed to the imgAreaSelect plugin in |
||
| 2516 | * wp.media.view.Cropper. |
||
| 2517 | * |
||
| 2518 | * @param {wp.media.model.Attachment} attachment |
||
| 2519 | * @param {wp.media.controller.Cropper} controller |
||
| 2520 | * @returns {Object} Options |
||
| 2521 | */ |
||
| 2522 | View Code Duplication | calculateImageSelectOptions: function( attachment, controller ) { |
|
| 2523 | |||
| 2524 | 'use strict'; |
||
| 2525 | |||
| 2526 | var control = controller.get( 'control' ), |
||
| 2527 | flexWidth = !! parseInt( control.params.flex_width, 10 ), |
||
| 2528 | flexHeight = !! parseInt( control.params.flex_height, 10 ), |
||
| 2529 | realWidth = attachment.get( 'width' ), |
||
| 2530 | realHeight = attachment.get( 'height' ), |
||
| 2531 | xInit = parseInt( control.params.width, 10 ), |
||
| 2532 | yInit = parseInt( control.params.height, 10 ), |
||
| 2533 | ratio = xInit / yInit, |
||
| 2534 | xImg = realWidth, |
||
| 2535 | yImg = realHeight, |
||
| 2536 | x1, |
||
| 2537 | y1, |
||
| 2538 | imgSelectOptions; |
||
| 2539 | |||
| 2540 | controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) ); |
||
| 2541 | |||
| 2542 | if ( xImg / yImg > ratio ) { |
||
| 2543 | yInit = yImg; |
||
| 2544 | xInit = yInit * ratio; |
||
| 2545 | } else { |
||
| 2546 | xInit = xImg; |
||
| 2547 | yInit = xInit / ratio; |
||
| 2548 | } |
||
| 2549 | |||
| 2550 | x1 = ( xImg - xInit ) / 2; |
||
| 2551 | y1 = ( yImg - yInit ) / 2; |
||
| 2552 | |||
| 2553 | imgSelectOptions = { |
||
| 2554 | handles: true, |
||
| 2555 | keys: true, |
||
| 2556 | instance: true, |
||
| 2557 | persistent: true, |
||
| 2558 | imageWidth: realWidth, |
||
| 2559 | imageHeight: realHeight, |
||
| 2560 | x1: x1, |
||
| 2561 | y1: y1, |
||
| 2562 | x2: xInit + x1, |
||
| 2563 | y2: yInit + y1 |
||
| 2564 | }; |
||
| 2565 | |||
| 2566 | if ( false === flexHeight && false === flexWidth ) { |
||
| 2567 | imgSelectOptions.aspectRatio = xInit + ':' + yInit; |
||
| 2568 | } |
||
| 2569 | if ( false === flexHeight ) { |
||
| 2570 | imgSelectOptions.maxHeight = yInit; |
||
| 2571 | } |
||
| 2572 | if ( false === flexWidth ) { |
||
| 2573 | imgSelectOptions.maxWidth = xInit; |
||
| 2574 | } |
||
| 2575 | |||
| 2576 | return imgSelectOptions; |
||
| 2577 | }, |
||
| 2578 | |||
| 2579 | /** |
||
| 2580 | * Return whether the image must be cropped, based on required dimensions. |
||
| 2581 | * |
||
| 2582 | * @param {bool} flexW |
||
| 2583 | * @param {bool} flexH |
||
| 2584 | * @param {int} dstW |
||
| 2585 | * @param {int} dstH |
||
| 2586 | * @param {int} imgW |
||
| 2587 | * @param {int} imgH |
||
| 2588 | * @return {bool} |
||
| 2589 | */ |
||
| 2590 | mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) { |
||
| 2591 | |||
| 2592 | 'use strict'; |
||
| 2593 | |||
| 2594 | if ( ( true === flexW && true === flexH ) || ( true === flexW && dstH === imgH ) || ( true === flexH && dstW === imgW ) || ( dstW === imgW && dstH === imgH ) || ( imgW <= dstW ) ) { |
||
| 2595 | return false; |
||
| 2596 | } |
||
| 2597 | |||
| 2598 | return true; |
||
| 2599 | }, |
||
| 2600 | |||
| 2601 | /** |
||
| 2602 | * If cropping was skipped, apply the image data directly to the setting. |
||
| 2603 | */ |
||
| 2604 | onSkippedCrop: function() { |
||
| 2605 | |||
| 2606 | 'use strict'; |
||
| 2607 | |||
| 2608 | var attachment = this.frame.state().get( 'selection' ).first().toJSON(); |
||
| 2609 | this.setImageInRepeaterField( attachment ); |
||
| 2610 | |||
| 2611 | }, |
||
| 2612 | |||
| 2613 | /** |
||
| 2614 | * Updates the setting and re-renders the control UI. |
||
| 2615 | * |
||
| 2616 | * @param {object} attachment |
||
| 2617 | */ |
||
| 2618 | setImageInRepeaterField: function( attachment ) { |
||
| 2619 | |||
| 2620 | 'use strict'; |
||
| 2621 | |||
| 2622 | var $targetDiv = this.$thisButton.closest( '.repeater-field-image,.repeater-field-cropped_image' ); |
||
| 2623 | |||
| 2624 | $targetDiv.find( '.kirki-image-attachment' ).html( '<img src="' + attachment.url + '">' ).hide().slideDown( 'slow' ); |
||
| 2625 | |||
| 2626 | $targetDiv.find( '.hidden-field' ).val( attachment.id ); |
||
| 2627 | this.$thisButton.text( this.$thisButton.data( 'alt-label' ) ); |
||
| 2628 | $targetDiv.find( '.remove-button' ).show(); |
||
| 2629 | |||
| 2630 | //This will activate the save button |
||
| 2631 | $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); |
||
| 2632 | this.frame.close(); |
||
| 2633 | |||
| 2634 | }, |
||
| 2635 | |||
| 2636 | /** |
||
| 2637 | * Updates the setting and re-renders the control UI. |
||
| 2638 | * |
||
| 2639 | * @param {object} attachment |
||
| 2640 | */ |
||
| 2641 | setFileInRepeaterField: function( attachment ) { |
||
| 2642 | |||
| 2643 | 'use strict'; |
||
| 2644 | |||
| 2645 | var $targetDiv = this.$thisButton.closest( '.repeater-field-upload' ); |
||
| 2646 | |||
| 2647 | $targetDiv.find( '.kirki-file-attachment' ).html( '<span class="file"><span class="dashicons dashicons-media-default"></span> ' + attachment.filename + '</span>' ).hide().slideDown( 'slow' ); |
||
| 2648 | |||
| 2649 | $targetDiv.find( '.hidden-field' ).val( attachment.id ); |
||
| 2650 | this.$thisButton.text( this.$thisButton.data( 'alt-label' ) ); |
||
| 2651 | $targetDiv.find( '.upload-button' ).show(); |
||
| 2652 | $targetDiv.find( '.remove-button' ).show(); |
||
| 2653 | |||
| 2654 | //This will activate the save button |
||
| 2655 | $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); |
||
| 2656 | this.frame.close(); |
||
| 2657 | |||
| 2658 | }, |
||
| 2659 | |||
| 2660 | getMimeType: function() { |
||
| 2661 | |||
| 2662 | 'use strict'; |
||
| 2663 | |||
| 2664 | // We get the field id from which this was called |
||
| 2665 | var currentFieldId = this.$thisButton.siblings( 'input.hidden-field' ).attr( 'data-field' ); |
||
| 2666 | |||
| 2667 | // Make sure we got it |
||
| 2668 | if ( _.isString( currentFieldId ) && '' !== currentFieldId ) { |
||
| 2669 | |||
| 2670 | // Make fields is defined and only do the hack for cropped_image |
||
| 2671 | if ( _.isObject( this.params.fields[ currentFieldId ] ) && 'upload' === this.params.fields[ currentFieldId ].type ) { |
||
| 2672 | |||
| 2673 | // If the attribute exists in the field |
||
| 2674 | if ( ! _.isUndefined( this.params.fields[ currentFieldId ].mime_type ) ) { |
||
| 2675 | |||
| 2676 | // Set the attribute in the main object |
||
| 2677 | return this.params.fields[ currentFieldId ].mime_type; |
||
| 2678 | } |
||
| 2679 | } |
||
| 2680 | } |
||
| 2681 | return 'image'; |
||
| 2682 | |||
| 2683 | }, |
||
| 2684 | |||
| 2685 | removeImage: function( event ) { |
||
| 2686 | |||
| 2687 | 'use strict'; |
||
| 2688 | |||
| 2689 | var $targetDiv, |
||
| 2690 | $uploadButton; |
||
| 2691 | |||
| 2692 | if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { |
||
| 2693 | return; |
||
| 2694 | } |
||
| 2695 | |||
| 2696 | $targetDiv = this.$thisButton.closest( '.repeater-field-image,.repeater-field-cropped_image,.repeater-field-upload' ); |
||
| 2697 | $uploadButton = $targetDiv.find( '.upload-button' ); |
||
| 2698 | |||
| 2699 | $targetDiv.find( '.kirki-image-attachment' ).slideUp( 'fast', function() { |
||
| 2700 | jQuery( this ).show().html( jQuery( this ).data( 'placeholder' ) ); |
||
| 2701 | }); |
||
| 2702 | $targetDiv.find( '.hidden-field' ).val( '' ); |
||
| 2703 | $uploadButton.text( $uploadButton.data( 'label' ) ); |
||
| 2704 | this.$thisButton.hide(); |
||
| 2705 | |||
| 2706 | $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); |
||
| 2707 | |||
| 2708 | }, |
||
| 2709 | |||
| 2710 | removeFile: function( event ) { |
||
| 2711 | |||
| 2712 | 'use strict'; |
||
| 2713 | |||
| 2714 | var $targetDiv, |
||
| 2715 | $uploadButton; |
||
| 2716 | |||
| 2717 | if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { |
||
| 2718 | return; |
||
| 2719 | } |
||
| 2720 | |||
| 2721 | $targetDiv = this.$thisButton.closest( '.repeater-field-upload' ); |
||
| 2722 | $uploadButton = $targetDiv.find( '.upload-button' ); |
||
| 2723 | |||
| 2724 | $targetDiv.find( '.kirki-file-attachment' ).slideUp( 'fast', function() { |
||
| 2725 | jQuery( this ).show().html( jQuery( this ).data( 'placeholder' ) ); |
||
| 2726 | }); |
||
| 2727 | $targetDiv.find( '.hidden-field' ).val( '' ); |
||
| 2728 | $uploadButton.text( $uploadButton.data( 'label' ) ); |
||
| 2729 | this.$thisButton.hide(); |
||
| 2730 | |||
| 2731 | $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); |
||
| 2732 | |||
| 2733 | }, |
||
| 2734 | |||
| 2735 | /** |
||
| 2736 | * Get the current value of the setting |
||
| 2737 | * |
||
| 2738 | * @return Object |
||
| 2739 | */ |
||
| 2740 | getValue: function() { |
||
| 2741 | |||
| 2742 | 'use strict'; |
||
| 2743 | |||
| 2744 | // The setting is saved in JSON |
||
| 2745 | return JSON.parse( decodeURI( this.setting.get() ) ); |
||
| 2746 | |||
| 2747 | }, |
||
| 2748 | |||
| 2749 | /** |
||
| 2750 | * Set a new value for the setting |
||
| 2751 | * |
||
| 2752 | * @param newValue Object |
||
| 2753 | * @param refresh If we want to refresh the previewer or not |
||
| 2754 | */ |
||
| 2755 | setValue: function( newValue, refresh, filtering ) { |
||
| 2756 | |||
| 2757 | 'use strict'; |
||
| 2758 | |||
| 2759 | // We need to filter the values after the first load to remove data requrired for diplay but that we don't want to save in DB |
||
| 2760 | var filteredValue = newValue, |
||
| 2761 | filter = []; |
||
| 2762 | |||
| 2763 | if ( filtering ) { |
||
| 2764 | jQuery.each( this.params.fields, function( index, value ) { |
||
| 2765 | if ( 'image' === value.type || 'cropped_image' === value.type || 'upload' === value.type ) { |
||
| 2766 | filter.push( index ); |
||
| 2767 | } |
||
| 2768 | }); |
||
| 2769 | jQuery.each( newValue, function( index, value ) { |
||
| 2770 | jQuery.each( filter, function( ind, field ) { |
||
| 2771 | if ( ! _.isUndefined( value[ field ] ) && ! _.isUndefined( value[ field ].id ) ) { |
||
| 2772 | filteredValue[index][ field ] = value[ field ].id; |
||
| 2773 | } |
||
| 2774 | }); |
||
| 2775 | }); |
||
| 2776 | } |
||
| 2777 | |||
| 2778 | this.setting.set( encodeURI( JSON.stringify( filteredValue ) ) ); |
||
| 2779 | |||
| 2780 | if ( refresh ) { |
||
| 2781 | |||
| 2782 | // Trigger the change event on the hidden field so |
||
| 2783 | // previewer refresh the website on Customizer |
||
| 2784 | this.settingField.trigger( 'change' ); |
||
| 2785 | } |
||
| 2786 | }, |
||
| 2787 | |||
| 2788 | /** |
||
| 2789 | * Add a new row to repeater settings based on the structure. |
||
| 2790 | * |
||
| 2791 | * @param data (Optional) Object of field => value pairs (undefined if you want to get the default values) |
||
| 2792 | */ |
||
| 2793 | addRow: function( data ) { |
||
| 2794 | |||
| 2795 | 'use strict'; |
||
| 2796 | |||
| 2797 | var control = this, |
||
| 2798 | template = control.repeaterTemplate(), // The template for the new row (defined on Kirki_Customize_Repeater_Control::render_content() ). |
||
| 2799 | settingValue = this.getValue(), // Get the current setting value. |
||
| 2800 | newRowSetting = {}, // Saves the new setting data. |
||
| 2801 | templateData, // Data to pass to the template |
||
| 2802 | newRow, |
||
| 2803 | i; |
||
| 2804 | |||
| 2805 | if ( template ) { |
||
| 2806 | |||
| 2807 | // The control structure is going to define the new fields |
||
| 2808 | // We need to clone control.params.fields. Assigning it |
||
| 2809 | // ould result in a reference assignment. |
||
| 2810 | templateData = jQuery.extend( true, {}, control.params.fields ); |
||
| 2811 | |||
| 2812 | // But if we have passed data, we'll use the data values instead |
||
| 2813 | if ( data ) { |
||
| 2814 | for ( i in data ) { |
||
| 2815 | if ( data.hasOwnProperty( i ) && templateData.hasOwnProperty( i ) ) { |
||
| 2816 | templateData[ i ]['default'] = data[ i ]; |
||
| 2817 | } |
||
| 2818 | } |
||
| 2819 | } |
||
| 2820 | |||
| 2821 | templateData.index = this.currentIndex; |
||
| 2822 | |||
| 2823 | // Append the template content |
||
| 2824 | template = template( templateData ); |
||
| 2825 | |||
| 2826 | // Create a new row object and append the element |
||
| 2827 | newRow = new RepeaterRow( |
||
| 2828 | control.currentIndex, |
||
| 2829 | jQuery( template ).appendTo( control.repeaterFieldsContainer ), |
||
| 2830 | control.params.row_label, |
||
| 2831 | control |
||
| 2832 | ); |
||
| 2833 | |||
| 2834 | newRow.container.on( 'row:remove', function( e, rowIndex ) { |
||
| 2835 | control.deleteRow( rowIndex ); |
||
| 2836 | }); |
||
| 2837 | |||
| 2838 | newRow.container.on( 'row:update', function( e, rowIndex, fieldName, element ) { |
||
| 2839 | control.updateField.call( control, e, rowIndex, fieldName, element ); |
||
| 2840 | newRow.updateLabel(); |
||
| 2841 | }); |
||
| 2842 | |||
| 2843 | // Add the row to rows collection |
||
| 2844 | this.rows[ this.currentIndex ] = newRow; |
||
| 2845 | |||
| 2846 | for ( i in templateData ) { |
||
| 2847 | if ( templateData.hasOwnProperty( i ) ) { |
||
| 2848 | newRowSetting[ i ] = templateData[ i ]['default']; |
||
| 2849 | } |
||
| 2850 | } |
||
| 2851 | |||
| 2852 | settingValue[ this.currentIndex ] = newRowSetting; |
||
| 2853 | this.setValue( settingValue, true ); |
||
| 2854 | |||
| 2855 | this.currentIndex++; |
||
| 2856 | |||
| 2857 | return newRow; |
||
| 2858 | } |
||
| 2859 | }, |
||
| 2860 | |||
| 2861 | sort: function() { |
||
| 2862 | |||
| 2863 | 'use strict'; |
||
| 2864 | |||
| 2865 | var control = this, |
||
| 2866 | $rows = this.repeaterFieldsContainer.find( '.repeater-row' ), |
||
| 2867 | newOrder = [], |
||
| 2868 | settings = control.getValue(), |
||
| 2869 | newRows = [], |
||
| 2870 | newSettings = []; |
||
| 2871 | |||
| 2872 | $rows.each( function( i, element ) { |
||
| 2873 | newOrder.push( jQuery( element ).data( 'row' ) ); |
||
| 2874 | }); |
||
| 2875 | |||
| 2876 | jQuery.each( newOrder, function( newPosition, oldPosition ) { |
||
| 2877 | newRows[ newPosition ] = control.rows[ oldPosition ]; |
||
| 2878 | newRows[ newPosition ].setRowIndex( newPosition ); |
||
| 2879 | |||
| 2880 | newSettings[ newPosition ] = settings[ oldPosition ]; |
||
| 2881 | }); |
||
| 2882 | |||
| 2883 | control.rows = newRows; |
||
| 2884 | control.setValue( newSettings ); |
||
| 2885 | |||
| 2886 | }, |
||
| 2887 | |||
| 2888 | /** |
||
| 2889 | * Delete a row in the repeater setting |
||
| 2890 | * |
||
| 2891 | * @param index Position of the row in the complete Setting Array |
||
| 2892 | */ |
||
| 2893 | deleteRow: function( index ) { |
||
| 2894 | |||
| 2895 | 'use strict'; |
||
| 2896 | |||
| 2897 | var currentSettings = this.getValue(), |
||
| 2898 | row, |
||
| 2899 | i, |
||
| 2900 | prop; |
||
| 2901 | |||
| 2902 | if ( currentSettings[ index ] ) { |
||
| 2903 | |||
| 2904 | // Find the row |
||
| 2905 | row = this.rows[ index ]; |
||
| 2906 | if ( row ) { |
||
| 2907 | |||
| 2908 | // Remove the row settings |
||
| 2909 | delete currentSettings[ index ]; |
||
| 2910 | |||
| 2911 | // Remove the row from the rows collection |
||
| 2912 | delete this.rows[ index ]; |
||
| 2913 | |||
| 2914 | // Update the new setting values |
||
| 2915 | this.setValue( currentSettings, true ); |
||
| 2916 | |||
| 2917 | } |
||
| 2918 | |||
| 2919 | } |
||
| 2920 | |||
| 2921 | // Remap the row numbers |
||
| 2922 | i = 1; |
||
| 2923 | for ( prop in this.rows ) { |
||
| 2924 | if ( this.rows.hasOwnProperty( prop ) && this.rows[ prop ] ) { |
||
| 2925 | this.rows[ prop ].updateLabel(); |
||
| 2926 | i++; |
||
| 2927 | } |
||
| 2928 | } |
||
| 2929 | }, |
||
| 2930 | |||
| 2931 | /** |
||
| 2932 | * Update a single field inside a row. |
||
| 2933 | * Triggered when a field has changed |
||
| 2934 | * |
||
| 2935 | * @param e Event Object |
||
| 2936 | */ |
||
| 2937 | updateField: function( e, rowIndex, fieldId, element ) { |
||
| 2938 | |||
| 2939 | 'use strict'; |
||
| 2940 | |||
| 2941 | var type, |
||
| 2942 | row, |
||
| 2943 | currentSettings; |
||
| 2944 | |||
| 2945 | if ( ! this.rows[ rowIndex ] ) { |
||
| 2946 | return; |
||
| 2947 | } |
||
| 2948 | |||
| 2949 | if ( ! this.params.fields[ fieldId ] ) { |
||
| 2950 | return; |
||
| 2951 | } |
||
| 2952 | |||
| 2953 | type = this.params.fields[ fieldId].type; |
||
| 2954 | row = this.rows[ rowIndex ]; |
||
| 2955 | currentSettings = this.getValue(); |
||
| 2956 | |||
| 2957 | element = jQuery( element ); |
||
| 2958 | |||
| 2959 | if ( _.isUndefined( currentSettings[ row.rowIndex ][ fieldId ] ) ) { |
||
| 2960 | return; |
||
| 2961 | } |
||
| 2962 | |||
| 2963 | if ( 'checkbox' === type ) { |
||
| 2964 | currentSettings[ row.rowIndex ][ fieldId ] = element.is( ':checked' ); |
||
| 2965 | } else { |
||
| 2966 | |||
| 2967 | // Update the settings |
||
| 2968 | currentSettings[ row.rowIndex ][ fieldId ] = element.val(); |
||
| 2969 | } |
||
| 2970 | this.setValue( currentSettings, true ); |
||
| 2971 | }, |
||
| 2972 | |||
| 2973 | /** |
||
| 2974 | * Init the color picker on color fields |
||
| 2975 | * Called after AddRow |
||
| 2976 | * |
||
| 2977 | */ |
||
| 2978 | initColorPicker: function() { |
||
| 2979 | |||
| 2980 | 'use strict'; |
||
| 2981 | |||
| 2982 | var control = this, |
||
| 2983 | colorPicker = control.container.find( '.color-picker-hex' ), |
||
| 2984 | options = {}, |
||
| 2985 | fieldId = colorPicker.data( 'field' ); |
||
| 2986 | |||
| 2987 | // We check if the color palette parameter is defined. |
||
| 2988 | if ( ! _.isUndefined( fieldId ) && ! _.isUndefined( control.params.fields[ fieldId ] ) && ! _.isUndefined( control.params.fields[ fieldId ].palettes ) && _.isObject( control.params.fields[ fieldId ].palettes ) ) { |
||
| 2989 | options.palettes = control.params.fields[ fieldId ].palettes; |
||
| 2990 | } |
||
| 2991 | |||
| 2992 | // When the color picker value is changed we update the value of the field |
||
| 2993 | options.change = function( event, ui ) { |
||
| 2994 | |||
| 2995 | var currentPicker = jQuery( event.target ), |
||
| 2996 | row = currentPicker.closest( '.repeater-row' ), |
||
| 2997 | rowIndex = row.data( 'row' ), |
||
| 2998 | currentSettings = control.getValue(); |
||
| 2999 | |||
| 3000 | currentSettings[ rowIndex ][ currentPicker.data( 'field' ) ] = ui.color.toString(); |
||
| 3001 | control.setValue( currentSettings, true ); |
||
| 3002 | |||
| 3003 | }; |
||
| 3004 | |||
| 3005 | // Init the color picker |
||
| 3006 | if ( 0 !== colorPicker.length ) { |
||
| 3007 | colorPicker.wpColorPicker( options ); |
||
| 3008 | } |
||
| 3009 | }, |
||
| 3010 | |||
| 3011 | /** |
||
| 3012 | * Init the dropdown-pages field with selectWoo |
||
| 3013 | * Called after AddRow |
||
| 3014 | * |
||
| 3015 | * @param {object} theNewRow the row that was added to the repeater |
||
| 3016 | * @param {object} data the data for the row if we're initializing a pre-existing row |
||
| 3017 | * |
||
| 3018 | */ |
||
| 3019 | initSelect: function( theNewRow, data ) { |
||
| 3020 | |||
| 3021 | 'use strict'; |
||
| 3022 | |||
| 3023 | var control = this, |
||
| 3024 | dropdown = theNewRow.container.find( '.repeater-field select' ), |
||
| 3025 | $select, |
||
| 3026 | dataField, |
||
| 3027 | multiple, |
||
| 3028 | selectWooOptions = {}; |
||
| 3029 | |||
| 3030 | if ( 0 === dropdown.length ) { |
||
| 3031 | return; |
||
| 3032 | } |
||
| 3033 | |||
| 3034 | dataField = dropdown.data( 'field' ); |
||
| 3035 | multiple = jQuery( dropdown ).data( 'multiple' ); |
||
| 3036 | if ( 'undefed' !== multiple && jQuery.isNumeric( multiple ) ) { |
||
| 3037 | multiple = parseInt( multiple, 10 ); |
||
| 3038 | if ( 1 < multiple ) { |
||
| 3039 | selectWooOptions.maximumSelectionLength = multiple; |
||
| 3040 | } |
||
| 3041 | } |
||
| 3042 | |||
| 3043 | data = data || {}; |
||
| 3044 | data[ dataField ] = data[ dataField ] || ''; |
||
| 3045 | |||
| 3046 | $select = jQuery( dropdown ).selectWoo( selectWooOptions ).val( data[ dataField ] ); |
||
| 3047 | |||
| 3048 | this.container.on( 'change', '.repeater-field select', function( event ) { |
||
| 3049 | |||
| 3050 | var currentDropdown = jQuery( event.target ), |
||
| 3051 | row = currentDropdown.closest( '.repeater-row' ), |
||
| 3052 | rowIndex = row.data( 'row' ), |
||
| 3053 | currentSettings = control.getValue(); |
||
| 3054 | |||
| 3055 | currentSettings[ rowIndex ][ currentDropdown.data( 'field' ) ] = jQuery( this ).val(); |
||
| 3056 | control.setValue( currentSettings ); |
||
| 3057 | }); |
||
| 3058 | } |
||
| 3059 | }); |
||
| 3060 | wp.customize.controlConstructor['kirki-slider'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 3061 | |||
| 3062 | initKirkiControl: function() { |
||
| 3063 | var control = this, |
||
| 3064 | changeAction = ( 'postMessage' === control.setting.transport ) ? 'mousemove change' : 'change', |
||
| 3065 | rangeInput = control.container.find( 'input[type="range"]' ), |
||
| 3066 | textInput = control.container.find( 'input[type="text"]' ), |
||
| 3067 | value = control.setting._value; |
||
| 3068 | |||
| 3069 | // Set the initial value in the text input. |
||
| 3070 | textInput.attr( 'value', value ); |
||
| 3071 | |||
| 3072 | // If the range input value changes copy the value to the text input. |
||
| 3073 | rangeInput.on( 'mousemove change', function() { |
||
| 3074 | textInput.attr( 'value', rangeInput.val() ); |
||
| 3075 | } ); |
||
| 3076 | |||
| 3077 | // Save the value when the range input value changes. |
||
| 3078 | // This is separate from the above because of the postMessage differences. |
||
| 3079 | // If the control refreshes the preview pane, |
||
| 3080 | // we don't want a refresh for every change |
||
| 3081 | // but 1 final refresh when the value is changed. |
||
| 3082 | rangeInput.on( changeAction, function() { |
||
| 3083 | control.setting.set( rangeInput.val() ); |
||
| 3084 | } ); |
||
| 3085 | |||
| 3086 | // If the text input value changes, |
||
| 3087 | // copy the value to the range input |
||
| 3088 | // and then save. |
||
| 3089 | textInput.on( 'input paste change', function() { |
||
| 3090 | rangeInput.attr( 'value', textInput.val() ); |
||
| 3091 | control.setting.set( textInput.val() ); |
||
| 3092 | } ); |
||
| 3093 | |||
| 3094 | // If the reset button is clicked, |
||
| 3095 | // set slider and text input values to default |
||
| 3096 | // and hen save. |
||
| 3097 | control.container.find( '.slider-reset' ).on( 'click', function() { |
||
| 3098 | textInput.attr( 'value', control.params['default'] ); |
||
| 3099 | rangeInput.attr( 'value', control.params['default'] ); |
||
| 3100 | control.setting.set( textInput.val() ); |
||
| 3101 | } ); |
||
| 3102 | } |
||
| 3103 | }); |
||
| 3104 | /* global kirkiControlLoader */ |
||
| 3105 | wp.customize.controlConstructor['kirki-sortable'] = wp.customize.Control.extend({ |
||
| 3106 | |||
| 3107 | // When we're finished loading continue processing |
||
| 3108 | ready: function() { |
||
| 3109 | |||
| 3110 | 'use strict'; |
||
| 3111 | |||
| 3112 | var control = this; |
||
| 3113 | |||
| 3114 | // Init the control. |
||
| 3115 | if ( ! _.isUndefined( window.kirkiControlLoader ) && _.isFunction( kirkiControlLoader ) ) { |
||
| 3116 | kirkiControlLoader( control ); |
||
| 3117 | } else { |
||
| 3118 | control.initKirkiControl(); |
||
| 3119 | } |
||
| 3120 | }, |
||
| 3121 | |||
| 3122 | initKirkiControl: function() { |
||
| 3123 | |||
| 3124 | 'use strict'; |
||
| 3125 | |||
| 3126 | var control = this; |
||
| 3127 | |||
| 3128 | control.container.find( '.kirki-controls-loading-spinner' ).hide(); |
||
| 3129 | |||
| 3130 | // Set the sortable container. |
||
| 3131 | control.sortableContainer = control.container.find( 'ul.sortable' ).first(); |
||
| 3132 | |||
| 3133 | // Init sortable. |
||
| 3134 | control.sortableContainer.sortable({ |
||
| 3135 | |||
| 3136 | // Update value when we stop sorting. |
||
| 3137 | stop: function() { |
||
| 3138 | control.updateValue(); |
||
| 3139 | } |
||
| 3140 | }).disableSelection().find( 'li' ).each( function() { |
||
| 3141 | |||
| 3142 | // Enable/disable options when we click on the eye of Thundera. |
||
| 3143 | jQuery( this ).find( 'i.visibility' ).click( function() { |
||
| 3144 | jQuery( this ).toggleClass( 'dashicons-visibility-faint' ).parents( 'li:eq(0)' ).toggleClass( 'invisible' ); |
||
| 3145 | }); |
||
| 3146 | }).click( function() { |
||
| 3147 | |||
| 3148 | // Update value on click. |
||
| 3149 | control.updateValue(); |
||
| 3150 | }); |
||
| 3151 | }, |
||
| 3152 | |||
| 3153 | /** |
||
| 3154 | * Updates the sorting list |
||
| 3155 | */ |
||
| 3156 | updateValue: function() { |
||
| 3157 | |||
| 3158 | 'use strict'; |
||
| 3159 | |||
| 3160 | var control = this, |
||
| 3161 | newValue = []; |
||
| 3162 | |||
| 3163 | this.sortableContainer.find( 'li' ).each( function() { |
||
| 3164 | if ( ! jQuery( this ).is( '.invisible' ) ) { |
||
| 3165 | newValue.push( jQuery( this ).data( 'value' ) ); |
||
| 3166 | } |
||
| 3167 | }); |
||
| 3168 | control.setting.set( newValue ); |
||
| 3169 | } |
||
| 3170 | }); |
||
| 3171 | wp.customize.controlConstructor['kirki-switch'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 3172 | |||
| 3173 | initKirkiControl: function() { |
||
| 3174 | |||
| 3175 | 'use strict'; |
||
| 3176 | |||
| 3177 | var control = this, |
||
| 3178 | checkboxValue = control.setting._value; |
||
| 3179 | |||
| 3180 | // Save the value |
||
| 3181 | this.container.on( 'change', 'input', function() { |
||
| 3182 | checkboxValue = ( jQuery( this ).is( ':checked' ) ) ? true : false; |
||
| 3183 | control.setting.set( checkboxValue ); |
||
| 3184 | }); |
||
| 3185 | } |
||
| 3186 | }); |
||
| 3187 | wp.customize.controlConstructor['kirki-toggle'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 3188 | |||
| 3189 | initKirkiControl: function() { |
||
| 3190 | |||
| 3191 | var control = this, |
||
| 3192 | checkboxValue = control.setting._value; |
||
| 3193 | |||
| 3194 | // Save the value |
||
| 3195 | this.container.on( 'change', 'input', function() { |
||
| 3196 | checkboxValue = ( jQuery( this ).is( ':checked' ) ) ? true : false; |
||
| 3197 | control.setting.set( checkboxValue ); |
||
| 3198 | }); |
||
| 3199 | } |
||
| 3200 | }); |
||
| 3201 | /* global kirkiL10n, kirki */ |
||
| 3202 | wp.customize.controlConstructor['kirki-typography'] = wp.customize.kirkiDynamicControl.extend({ |
||
| 3203 | |||
| 3204 | View Code Duplication | initKirkiControl: function() { |
|
| 3205 | |||
| 3206 | 'use strict'; |
||
| 3207 | |||
| 3208 | var control = this, |
||
| 3209 | value = control.setting._value, |
||
| 3210 | picker; |
||
| 3211 | |||
| 3212 | control.renderFontSelector(); |
||
| 3213 | control.renderBackupFontSelector(); |
||
| 3214 | control.renderVariantSelector(); |
||
| 3215 | control.renderSubsetSelector(); |
||
| 3216 | |||
| 3217 | // Font-size. |
||
| 3218 | if ( control.params['default']['font-size'] ) { |
||
| 3219 | this.container.on( 'change keyup paste', '.font-size input', function() { |
||
| 3220 | control.saveValue( 'font-size', jQuery( this ).val() ); |
||
| 3221 | }); |
||
| 3222 | } |
||
| 3223 | |||
| 3224 | // Line-height. |
||
| 3225 | if ( control.params['default']['line-height'] ) { |
||
| 3226 | this.container.on( 'change keyup paste', '.line-height input', function() { |
||
| 3227 | control.saveValue( 'line-height', jQuery( this ).val() ); |
||
| 3228 | }); |
||
| 3229 | } |
||
| 3230 | |||
| 3231 | // Margin-top. |
||
| 3232 | if ( control.params['default']['margin-top'] ) { |
||
| 3233 | this.container.on( 'change keyup paste', '.margin-top input', function() { |
||
| 3234 | control.saveValue( 'margin-top', jQuery( this ).val() ); |
||
| 3235 | }); |
||
| 3236 | } |
||
| 3237 | |||
| 3238 | // Margin-bottom. |
||
| 3239 | if ( control.params['default']['margin-bottom'] ) { |
||
| 3240 | this.container.on( 'change keyup paste', '.margin-bottom input', function() { |
||
| 3241 | control.saveValue( 'margin-bottom', jQuery( this ).val() ); |
||
| 3242 | }); |
||
| 3243 | } |
||
| 3244 | |||
| 3245 | // Letter-spacing. |
||
| 3246 | if ( control.params['default']['letter-spacing'] ) { |
||
| 3247 | value['letter-spacing'] = ( jQuery.isNumeric( value['letter-spacing'] ) ) ? value['letter-spacing'] + 'px' : value['letter-spacing']; |
||
| 3248 | this.container.on( 'change keyup paste', '.letter-spacing input', function() { |
||
| 3249 | value['letter-spacing'] = ( jQuery.isNumeric( jQuery( this ).val() ) ) ? jQuery( this ).val() + 'px' : jQuery( this ).val(); |
||
| 3250 | control.saveValue( 'letter-spacing', value['letter-spacing'] ); |
||
| 3251 | }); |
||
| 3252 | } |
||
| 3253 | |||
| 3254 | // Word-spacing. |
||
| 3255 | if ( control.params['default']['word-spacing'] ) { |
||
| 3256 | this.container.on( 'change keyup paste', '.word-spacing input', function() { |
||
| 3257 | control.saveValue( 'word-spacing', jQuery( this ).val() ); |
||
| 3258 | }); |
||
| 3259 | } |
||
| 3260 | |||
| 3261 | // Text-align. |
||
| 3262 | if ( control.params['default']['text-align'] ) { |
||
| 3263 | this.container.on( 'change', '.text-align input', function() { |
||
| 3264 | control.saveValue( 'text-align', jQuery( this ).val() ); |
||
| 3265 | }); |
||
| 3266 | } |
||
| 3267 | |||
| 3268 | // Text-transform. |
||
| 3269 | if ( control.params['default']['text-transform'] ) { |
||
| 3270 | jQuery( control.selector + ' .text-transform select' ).selectWoo().on( 'change', function() { |
||
| 3271 | control.saveValue( 'text-transform', jQuery( this ).val() ); |
||
| 3272 | }); |
||
| 3273 | } |
||
| 3274 | |||
| 3275 | // Text-decoration. |
||
| 3276 | if ( control.params['default']['text-decoration'] ) { |
||
| 3277 | jQuery( control.selector + ' .text-decoration select' ).selectWoo().on( 'change', function() { |
||
| 3278 | control.saveValue( 'text-decoration', jQuery( this ).val() ); |
||
| 3279 | }); |
||
| 3280 | } |
||
| 3281 | |||
| 3282 | // Color. |
||
| 3283 | if ( control.params['default'].color ) { |
||
| 3284 | picker = this.container.find( '.kirki-color-control' ); |
||
| 3285 | picker.wpColorPicker({ |
||
| 3286 | change: function() { |
||
| 3287 | setTimeout( function() { |
||
| 3288 | control.saveValue( 'color', picker.val() ); |
||
| 3289 | }, 100 ); |
||
| 3290 | } |
||
| 3291 | }); |
||
| 3292 | } |
||
| 3293 | }, |
||
| 3294 | |||
| 3295 | /** |
||
| 3296 | * Adds the font-families to the font-family dropdown |
||
| 3297 | * and instantiates selectWoo. |
||
| 3298 | */ |
||
| 3299 | View Code Duplication | renderFontSelector: function() { |
|
| 3300 | |||
| 3301 | var control = this, |
||
| 3302 | selector = control.selector + ' .font-family select', |
||
| 3303 | data = [], |
||
| 3304 | standardFonts = [], |
||
| 3305 | googleFonts = [], |
||
| 3306 | value = control.setting._value, |
||
| 3307 | fonts = control.getFonts(), |
||
| 3308 | fontSelect; |
||
| 3309 | |||
| 3310 | // Format standard fonts as an array. |
||
| 3311 | if ( ! _.isUndefined( fonts.standard ) ) { |
||
| 3312 | _.each( fonts.standard, function( font ) { |
||
| 3313 | standardFonts.push({ |
||
| 3314 | id: font.family.replace( /"/g, ''' ), |
||
| 3315 | text: font.label |
||
| 3316 | }); |
||
| 3317 | }); |
||
| 3318 | } |
||
| 3319 | |||
| 3320 | // Format google fonts as an array. |
||
| 3321 | if ( ! _.isUndefined( fonts.google ) ) { |
||
| 3322 | _.each( fonts.google, function( font ) { |
||
| 3323 | googleFonts.push({ |
||
| 3324 | id: font.family, |
||
| 3325 | text: font.family |
||
| 3326 | }); |
||
| 3327 | }); |
||
| 3328 | } |
||
| 3329 | |||
| 3330 | // Combine forces and build the final data. |
||
| 3331 | data = [ |
||
| 3332 | { text: kirkiL10n.standardFonts, children: standardFonts }, |
||
| 3333 | { text: kirkiL10n.googleFonts, children: googleFonts } |
||
| 3334 | ]; |
||
| 3335 | |||
| 3336 | // Instantiate selectWoo with the data. |
||
| 3337 | fontSelect = jQuery( selector ).selectWoo({ |
||
| 3338 | data: data |
||
| 3339 | }); |
||
| 3340 | |||
| 3341 | // Set the initial value. |
||
| 3342 | if ( value['font-family'] ) { |
||
| 3343 | fontSelect.val( value['font-family'].replace( /'/g, '"' ) ).trigger( 'change' ); |
||
| 3344 | } |
||
| 3345 | |||
| 3346 | // When the value changes |
||
| 3347 | fontSelect.on( 'change', function() { |
||
| 3348 | |||
| 3349 | // Set the value. |
||
| 3350 | control.saveValue( 'font-family', jQuery( this ).val() ); |
||
| 3351 | |||
| 3352 | // Re-init the font-backup selector. |
||
| 3353 | control.renderBackupFontSelector(); |
||
| 3354 | |||
| 3355 | // Re-init variants selector. |
||
| 3356 | control.renderVariantSelector(); |
||
| 3357 | |||
| 3358 | // Re-init subsets selector. |
||
| 3359 | control.renderSubsetSelector(); |
||
| 3360 | }); |
||
| 3361 | }, |
||
| 3362 | |||
| 3363 | /** |
||
| 3364 | * Adds the font-families to the font-family dropdown |
||
| 3365 | * and instantiates selectWoo. |
||
| 3366 | */ |
||
| 3367 | renderBackupFontSelector: function() { |
||
| 3368 | |||
| 3369 | var control = this, |
||
| 3370 | selector = control.selector + ' .font-backup select', |
||
| 3371 | standardFonts = [], |
||
| 3372 | value = control.setting._value, |
||
| 3373 | fontFamily = value['font-family'], |
||
| 3374 | fonts = control.getFonts(), |
||
| 3375 | fontSelect; |
||
| 3376 | |||
| 3377 | if ( _.isUndefined( value['font-backup'] ) || null === value['font-backup'] ) { |
||
| 3378 | value['font-backup'] = ''; |
||
| 3379 | } |
||
| 3380 | |||
| 3381 | // Hide if we're not on a google-font. |
||
| 3382 | if ( 'google' !== kirki.util.webfonts.getFontType( fontFamily ) ) { |
||
| 3383 | jQuery( control.selector + ' .font-backup' ).hide(); |
||
| 3384 | return; |
||
| 3385 | } |
||
| 3386 | jQuery( control.selector + ' .font-backup' ).show(); |
||
| 3387 | |||
| 3388 | // Format standard fonts as an array. |
||
| 3389 | if ( ! _.isUndefined( fonts.standard ) ) { |
||
| 3390 | _.each( fonts.standard, function( font ) { |
||
| 3391 | standardFonts.push({ |
||
| 3392 | id: font.family.replace( /"/g, ''' ), |
||
| 3393 | text: font.label |
||
| 3394 | }); |
||
| 3395 | }); |
||
| 3396 | } |
||
| 3397 | |||
| 3398 | // Instantiate selectWoo with the data. |
||
| 3399 | fontSelect = jQuery( selector ).selectWoo({ |
||
| 3400 | data: standardFonts |
||
| 3401 | }); |
||
| 3402 | |||
| 3403 | // Set the initial value. |
||
| 3404 | if ( 'undefined' !== typeof value['font-backup'] ) { |
||
| 3405 | fontSelect.val( value['font-backup'].replace( /'/g, '"' ) ).trigger( 'change' ); |
||
| 3406 | } |
||
| 3407 | |||
| 3408 | // When the value changes |
||
| 3409 | fontSelect.on( 'change', function() { |
||
| 3410 | |||
| 3411 | // Set the value. |
||
| 3412 | control.saveValue( 'font-backup', jQuery( this ).val() ); |
||
| 3413 | }); |
||
| 3414 | }, |
||
| 3415 | |||
| 3416 | /** |
||
| 3417 | * Renders the variants selector using selectWoo |
||
| 3418 | * Displays font-variants for the currently selected font-family. |
||
| 3419 | */ |
||
| 3420 | renderVariantSelector: function() { |
||
| 3421 | |||
| 3422 | var control = this, |
||
| 3423 | value = control.setting._value, |
||
| 3424 | fontFamily = value['font-family'], |
||
| 3425 | selector = control.selector + ' .variant select', |
||
| 3426 | data = [], |
||
| 3427 | isValid = false, |
||
| 3428 | fontType = kirki.util.webfonts.getFontType( fontFamily ), |
||
| 3429 | variants = ['regular', 'italic', '700', '700italic'], |
||
| 3430 | fontWeight, |
||
| 3431 | variantSelector, |
||
| 3432 | fontStyle; |
||
| 3433 | |||
| 3434 | if ( 'google' === fontType ) { |
||
| 3435 | variants = kirki.util.webfonts.google.getVariants( fontFamily ); |
||
| 3436 | } |
||
| 3437 | |||
| 3438 | jQuery( control.selector + ' .variant' ).show(); |
||
| 3439 | _.each( variants, function( variant ) { |
||
| 3440 | if ( value.variant === variant ) { |
||
| 3441 | isValid = true; |
||
| 3442 | } |
||
| 3443 | data.push({ |
||
| 3444 | id: variant, |
||
| 3445 | text: variant |
||
| 3446 | }); |
||
| 3447 | }); |
||
| 3448 | if ( ! isValid ) { |
||
| 3449 | value.variant = 'regular'; |
||
| 3450 | } |
||
| 3451 | |||
| 3452 | if ( jQuery( selector ).hasClass( 'select2-hidden-accessible' ) ) { |
||
| 3453 | jQuery( selector ).selectWoo( 'destroy' ); |
||
| 3454 | jQuery( selector ).empty(); |
||
| 3455 | } |
||
| 3456 | |||
| 3457 | // Instantiate selectWoo with the data. |
||
| 3458 | variantSelector = jQuery( selector ).selectWoo({ |
||
| 3459 | data: data |
||
| 3460 | }); |
||
| 3461 | variantSelector.val( value.variant ).trigger( 'change' ); |
||
| 3462 | variantSelector.on( 'change', function() { |
||
| 3463 | control.saveValue( 'variant', jQuery( this ).val() ); |
||
| 3464 | |||
| 3465 | fontWeight = ( ! _.isString( value.variant ) ) ? '400' : value.variant.match( /\d/g ); |
||
| 3466 | fontWeight = ( ! _.isObject( fontWeight ) ) ? '400' : fontWeight.join( '' ); |
||
| 3467 | fontStyle = ( -1 !== value.variant.indexOf( 'italic' ) ) ? 'italic' : 'normal'; |
||
| 3468 | |||
| 3469 | control.saveValue( 'font-weight', fontWeight ); |
||
| 3470 | control.saveValue( 'font-style', fontStyle ); |
||
| 3471 | }); |
||
| 3472 | }, |
||
| 3473 | |||
| 3474 | /** |
||
| 3475 | * Renders the subsets selector using selectWoo |
||
| 3476 | * Displays font-subsets for the currently selected font-family. |
||
| 3477 | */ |
||
| 3478 | renderSubsetSelector: function() { |
||
| 3479 | |||
| 3480 | var control = this, |
||
| 3481 | value = control.setting._value, |
||
| 3482 | fontFamily = value['font-family'], |
||
| 3483 | subsets = kirki.util.webfonts.google.getSubsets( fontFamily ), |
||
| 3484 | selector = control.selector + ' .subsets select', |
||
| 3485 | data = [], |
||
| 3486 | validValue = value.subsets, |
||
| 3487 | subsetSelector; |
||
| 3488 | |||
| 3489 | if ( false !== subsets ) { |
||
| 3490 | jQuery( control.selector + ' .subsets' ).show(); |
||
| 3491 | _.each( subsets, function( subset ) { |
||
| 3492 | |||
| 3493 | if ( _.isObject( validValue ) ) { |
||
| 3494 | if ( -1 === validValue.indexOf( subset ) ) { |
||
| 3495 | validValue = _.reject( validValue, function( subValue ) { |
||
| 3496 | return subValue === subset; |
||
| 3497 | }); |
||
| 3498 | } |
||
| 3499 | } |
||
| 3500 | |||
| 3501 | data.push({ |
||
| 3502 | id: subset, |
||
| 3503 | text: subset |
||
| 3504 | }); |
||
| 3505 | }); |
||
| 3506 | |||
| 3507 | } else { |
||
| 3508 | jQuery( control.selector + ' .subsets' ).hide(); |
||
| 3509 | } |
||
| 3510 | |||
| 3511 | if ( jQuery( selector ).hasClass( 'select2-hidden-accessible' ) ) { |
||
| 3512 | jQuery( selector ).selectWoo( 'destroy' ); |
||
| 3513 | jQuery( selector ).empty(); |
||
| 3514 | } |
||
| 3515 | |||
| 3516 | // Instantiate selectWoo with the data. |
||
| 3517 | subsetSelector = jQuery( selector ).selectWoo({ |
||
| 3518 | data: data |
||
| 3519 | }); |
||
| 3520 | subsetSelector.val( validValue ).trigger( 'change' ); |
||
| 3521 | subsetSelector.on( 'change', function() { |
||
| 3522 | control.saveValue( 'subsets', jQuery( this ).val() ); |
||
| 3523 | }); |
||
| 3524 | }, |
||
| 3525 | |||
| 3526 | /** |
||
| 3527 | * Get fonts. |
||
| 3528 | */ |
||
| 3529 | getFonts: function() { |
||
| 3530 | var control = this, |
||
| 3531 | initialGoogleFonts = kirki.util.webfonts.google.getFonts(), |
||
| 3532 | googleFonts = {}, |
||
| 3533 | googleFontsSort = 'alpha', |
||
| 3534 | googleFontsNumber = 0, |
||
| 3535 | standardFonts = {}; |
||
| 3536 | |||
| 3537 | // Get google fonts. |
||
| 3538 | if ( ! _.isEmpty( control.params.choices.fonts.google ) ) { |
||
| 3539 | if ( 'alpha' === control.params.choices.fonts.google[0] || 'popularity' === control.params.choices.fonts.google[0] || 'trending' === control.params.choices.fonts.google[0] ) { |
||
| 3540 | googleFontsSort = control.params.choices.fonts.google[0]; |
||
| 3541 | if ( ! isNaN( control.params.choices.fonts.google[1] ) ) { |
||
| 3542 | googleFontsNumber = parseInt( control.params.choices.fonts.google[1], 10 ); |
||
| 3543 | } |
||
| 3544 | googleFonts = kirki.util.webfonts.google.getFonts( googleFontsSort, googleFontsNumber ); |
||
| 3545 | |||
| 3546 | } else { |
||
| 3547 | _.each( control.params.choices.fonts.google, function( fontName ) { |
||
| 3548 | if ( 'undefined' !== typeof initialGoogleFonts[ fontName ] && ! _.isEmpty( initialGoogleFonts[ fontName ] ) ) { |
||
| 3549 | googleFonts[ fontName ] = initialGoogleFonts[ fontName ]; |
||
| 3550 | } |
||
| 3551 | } ); |
||
| 3552 | } |
||
| 3553 | } else { |
||
| 3554 | googleFonts = kirki.util.webfonts.google.getFonts( googleFontsSort, googleFontsNumber ); |
||
| 3555 | } |
||
| 3556 | |||
| 3557 | // Get standard fonts. |
||
| 3558 | if ( ! _.isEmpty( control.params.choices.fonts.standard ) ) { |
||
| 3559 | _.each( control.params.choices.fonts.standard, function( fontName ) { |
||
| 3560 | if ( 'undefined' !== typeof kirki.util.webfonts.standard.fonts[ fontName ] && ! _.isEmpty( kirki.util.webfonts.standard.fonts[ fontName ] ) ) { |
||
| 3561 | standardFonts[ fontName ] = {}; |
||
| 3562 | if ( 'undefined' !== kirki.util.webfonts.standard.fonts[ fontName ].stack && ! _.isEmpty( kirki.util.webfonts.standard.fonts[ fontName ].stack ) ) { |
||
| 3563 | standardFonts[ fontName ].family = kirki.util.webfonts.standard.fonts[ fontName ].stack; |
||
| 3564 | } else { |
||
| 3565 | standardFonts[ fontName ].family = googleFonts[ fontName ]; |
||
| 3566 | } |
||
| 3567 | if ( 'undefined' !== kirki.util.webfonts.standard.fonts[ fontName ].label && ! _.isEmpty( kirki.util.webfonts.standard.fonts[ fontName ].label ) ) { |
||
| 3568 | standardFonts[ fontName ].label = kirki.util.webfonts.standard.fonts[ fontName ].label; |
||
| 3569 | } else if ( ! _.isEmpty( standardFonts[ fontName ] ) ) { |
||
| 3570 | standardFonts[ fontName ].label = standardFonts[ fontName ]; |
||
| 3571 | } |
||
| 3572 | } else { |
||
| 3573 | standardFonts[ fontName ] = { |
||
| 3574 | family: fontName, |
||
| 3575 | label: fontName |
||
| 3576 | }; |
||
| 3577 | } |
||
| 3578 | } ); |
||
| 3579 | } else { |
||
| 3580 | _.each( kirki.util.webfonts.standard.fonts, function( font, id ) { |
||
| 3581 | standardFonts[ id ] = { |
||
| 3582 | family: font.stack, |
||
| 3583 | label: font.label |
||
| 3584 | }; |
||
| 3585 | } ); |
||
| 3586 | } |
||
| 3587 | return { |
||
| 3588 | google: googleFonts, |
||
| 3589 | standard: standardFonts |
||
| 3590 | }; |
||
| 3591 | }, |
||
| 3592 | |||
| 3593 | /** |
||
| 3594 | * Saves the value. |
||
| 3595 | */ |
||
| 3596 | saveValue: function( property, value ) { |
||
| 3597 | |||
| 3598 | var control = this, |
||
| 3599 | input = control.container.find( '.typography-hidden-value' ), |
||
| 3600 | val = control.setting._value; |
||
| 3601 | |||
| 3602 | val[ property ] = value; |
||
| 3603 | |||
| 3604 | jQuery( input ).attr( 'value', JSON.stringify( val ) ).trigger( 'change' ); |
||
| 3605 | control.setting.set( val ); |
||
| 3606 | } |
||
| 3607 | }); |
||
| 3608 |