| 1 |
/** @namespace customify */ |
| 2 |
window.customify = window.customify || parent.customify || {}; |
| 3 |
|
| 4 |
(function ($, customify, wp) { |
| 5 |
const api = wp.customize |
| 6 |
const $window = $(window) |
| 7 |
const $document = $(document) |
| 8 |
let timeout = null |
| 9 |
|
| 10 |
// when the customizer is ready prepare our fields events |
| 11 |
api.bind('ready', function () { |
| 12 |
|
| 13 |
// Create a stack of callbacks bound to parent settings to be able to unbind them |
| 14 |
// when altering the connected_fields attribute. |
| 15 |
if (typeof customify.connectedFieldsCallbacks === 'undefined') { |
| 16 |
customify.connectedFieldsCallbacks = {} |
| 17 |
} |
| 18 |
|
| 19 |
// Initialize ACE editors. |
| 20 |
handleAceEditors() |
| 21 |
|
| 22 |
// Initialize simple select2 fields. |
| 23 |
$('.customify_select2').select2() |
| 24 |
|
| 25 |
// Initialize font fields. |
| 26 |
customify.fontFields.init() |
| 27 |
|
| 28 |
// For each range input add a value preview output. |
| 29 |
$('.accordion-section-content[id*="' + customify.config.options_name + '"], #sub-accordion-section-style_manager_section').each(function () { |
| 30 |
// Initialize range fields logic |
| 31 |
handleRangeFields(this) |
| 32 |
}) |
| 33 |
|
| 34 |
// Handle presets (legacy). |
| 35 |
handlePresets() |
| 36 |
|
| 37 |
// Initialize custom background fields. |
| 38 |
customifyBackgroundJsControl.init() |
| 39 |
|
| 40 |
setTimeout(function () { |
| 41 |
customifyFoldingFields() |
| 42 |
}, 1000) |
| 43 |
|
| 44 |
// Handle reset buttons |
| 45 |
handleResetButtons() |
| 46 |
|
| 47 |
// Handle the section tabs (ex: Layout | Fonts | Colors) |
| 48 |
handleSectionTabs() |
| 49 |
|
| 50 |
// Bind any connected fields, except those in the Style Manager. |
| 51 |
// Those are handled by the appropriate Style Manager component (Color Palettes, Font Palettes, etc ). |
| 52 |
bindConnectedFields() |
| 53 |
|
| 54 |
// Handle the preview iframe. |
| 55 |
handlePreviewIframe() |
| 56 |
|
| 57 |
// Sometimes a php save may be needed. Trigger it if the appropiate URL var is present. |
| 58 |
if (getUrlVar('save_customizer_once')) { |
| 59 |
api.previewer.save() |
| 60 |
} |
| 61 |
}) |
| 62 |
|
| 63 |
/** |
| 64 |
* Handle the ACE editor fields. |
| 65 |
*/ |
| 66 |
function handleAceEditors () { |
| 67 |
$('.customify_ace_editor').each(function (key, el) { |
| 68 |
const id = $(this).attr('id'), |
| 69 |
cssEditorInstance = ace.edit(id) |
| 70 |
|
| 71 |
const editor_type = $(this).data('editor_type') |
| 72 |
// init the ace editor |
| 73 |
cssEditorInstance.setTheme('ace/theme/github') |
| 74 |
cssEditorInstance.getSession().setMode('ace/mode/' + editor_type) |
| 75 |
|
| 76 |
// hide the textarea and enable the ace editor |
| 77 |
const textarea = $('#' + id + '_textarea').hide() |
| 78 |
cssEditorInstance.getSession().setValue(textarea.val()) |
| 79 |
|
| 80 |
// each time a change is triggered start a timeout of 1,5s and when is finished refresh the previewer |
| 81 |
// if the user types faster than this delay then reset it |
| 82 |
cssEditorInstance.getSession().on('change', function (event) { |
| 83 |
if (timeout !== null) { |
| 84 |
clearTimeout(timeout) |
| 85 |
timeout = null |
| 86 |
} else { |
| 87 |
timeout = setTimeout(function () { |
| 88 |
textarea.val(cssEditorInstance.getSession().getValue()) |
| 89 |
textarea.trigger('change', ['customify']) |
| 90 |
}, 1500) |
| 91 |
} |
| 92 |
}) |
| 93 |
}) |
| 94 |
} |
| 95 |
|
| 96 |
/** |
| 97 |
* Handle the presets (legacy). |
| 98 |
*/ |
| 99 |
function handlePresets () { |
| 100 |
$('body').on('customify:preset-change', function (event) { |
| 101 |
const data = $(event.target).data('options') |
| 102 |
|
| 103 |
if (!_.isUndefined(data)) { |
| 104 |
$.each(data, function (settingID, value) { |
| 105 |
apiSetSettingValue(settingID, value) |
| 106 |
}) |
| 107 |
} |
| 108 |
}) |
| 109 |
$document.on('change', 'select.js-customify-preset', function () { |
| 110 |
const $source = $(this) |
| 111 |
const $target = $source.children('[value="' + $source.val() + '"]') |
| 112 |
$target.trigger('customify:preset-change') |
| 113 |
}) |
| 114 |
$document.on('click', '.js-customify-preset input', function () { |
| 115 |
$(this).trigger('customify:preset-change') |
| 116 |
}) |
| 117 |
} |
| 118 |
|
| 119 |
const handleRangeFields = function (el) { |
| 120 |
|
| 121 |
// For each range input add a number field (for preview mainly - but it can also be used for input) |
| 122 |
$(el).find('input[type="range"]').each(function () { |
| 123 |
const $range = $(this) |
| 124 |
let $number = $range.siblings('.range-value') |
| 125 |
|
| 126 |
if (!$number.length) { |
| 127 |
$number = $range.clone() |
| 128 |
|
| 129 |
$number |
| 130 |
.attr('type', 'number') |
| 131 |
.attr('class', 'range-value') |
| 132 |
.removeAttr('data-value_entry') |
| 133 |
|
| 134 |
if ($range.first().attr('id')) { |
| 135 |
$number.attr('id', $range.first().attr('id') + '_number') |
| 136 |
} |
| 137 |
$number.insertAfter($range) |
| 138 |
} |
| 139 |
|
| 140 |
function hasValidValue ($input) { |
| 141 |
const min = $input.attr('min') |
| 142 |
const max = $input.attr('max') |
| 143 |
const value = $input.val() |
| 144 |
|
| 145 |
if (typeof min !== 'undefined' && parseFloat(min) > parseFloat(value)) { |
| 146 |
return false |
| 147 |
} |
| 148 |
|
| 149 |
return !(typeof max !== 'undefined' && parseFloat(max) < parseFloat(value)) |
| 150 |
} |
| 151 |
|
| 152 |
// Put the value into the number field. |
| 153 |
$range.on('input change', function (event) { |
| 154 |
if (event.target.value === $number.val()) { |
| 155 |
// Nothing to do if the values are identical. |
| 156 |
return; |
| 157 |
} |
| 158 |
|
| 159 |
$number.val($range.val()) |
| 160 |
}) |
| 161 |
|
| 162 |
// When clicking outside the number field or on Enter. |
| 163 |
$number.on('blur keyup', function (event) { |
| 164 |
if ('keyup' === event.type && event.keyCode !== 13) { |
| 165 |
return |
| 166 |
} |
| 167 |
|
| 168 |
if (event.target.value === $range.val()) { |
| 169 |
// Nothing to do if the values are identical. |
| 170 |
return; |
| 171 |
} |
| 172 |
|
| 173 |
if (!hasValidValue($number)) { |
| 174 |
$number.val($range.val()) |
| 175 |
shake($number) |
| 176 |
} else { |
| 177 |
// Do not mark this trigger as being programmatically triggered by Customify since it is a result of a user input. |
| 178 |
$range.val($number.val()).trigger('change') |
| 179 |
} |
| 180 |
}) |
| 181 |
|
| 182 |
function shake ($field) { |
| 183 |
$field.addClass('input-shake input-error') |
| 184 |
$field.one('animationend', function () { |
| 185 |
$field.removeClass('input-shake input-error') |
| 186 |
}) |
| 187 |
} |
| 188 |
}) |
| 189 |
} |
| 190 |
|
| 191 |
/** |
| 192 |
* Handle reset buttons in the Customizer. |
| 193 |
*/ |
| 194 |
function handleResetButtons () { |
| 195 |
const showResetButtons = $('button[data-action="reset_customify"]').length > 0 |
| 196 |
|
| 197 |
if (showResetButtons) { |
| 198 |
createResetPanelButtons() |
| 199 |
createResetSectionButtons() |
| 200 |
|
| 201 |
$document.on('click', '.js-reset-panel', onResetPanel) |
| 202 |
$document.on('click', '.js-reset-section', onResetSection) |
| 203 |
$document.on('click', '#customize-control-reset_customify button', onReset) |
| 204 |
} |
| 205 |
} |
| 206 |
|
| 207 |
function createResetPanelButtons () { |
| 208 |
|
| 209 |
$('.panel-meta').each(function (i, obj) { |
| 210 |
const $this = $(obj) |
| 211 |
const container = $this.parents('.control-panel') |
| 212 |
let id = container.attr('id') |
| 213 |
|
| 214 |
if (typeof id !== 'undefined') { |
| 215 |
id = id.replace('sub-accordion-panel-', '') |
| 216 |
id = id.replace('accordion-panel-', '') |
| 217 |
const $buttonWrapper = $('<li class="customize-control customize-control-reset"></li>') |
| 218 |
const $button = $('<button class="button js-reset-panel" data-panel="' + id + '"></button>') |
| 219 |
|
| 220 |
$button.text(customify.l10n.panelResetButton).appendTo($buttonWrapper) |
| 221 |
$this.parent().append($buttonWrapper) |
| 222 |
} |
| 223 |
}) |
| 224 |
} |
| 225 |
|
| 226 |
function createResetSectionButtons () { |
| 227 |
$('.accordion-section-content').each(function (el, key) { |
| 228 |
const $this = $(this) |
| 229 |
const sectionID = $this.attr('id') |
| 230 |
|
| 231 |
if (_.isUndefined(sectionID) || sectionID.indexOf(customify.config.options_name) === -1) { |
| 232 |
return |
| 233 |
} |
| 234 |
|
| 235 |
const id = sectionID.replace('sub-accordion-section-', '') |
| 236 |
const $button = $('<button class="button js-reset-section" data-section="' + id + '"></button>') |
| 237 |
const $buttonWrapper = $('<li class="customize-control customize-control-reset"></li>') |
| 238 |
|
| 239 |
$button.text(customify.l10n.sectionResetButton) |
| 240 |
$buttonWrapper.append($button) |
| 241 |
|
| 242 |
$this.append($buttonWrapper) |
| 243 |
}) |
| 244 |
} |
| 245 |
|
| 246 |
function onReset (ev) { |
| 247 |
ev.preventDefault() |
| 248 |
|
| 249 |
const iAgree = confirm(customify.l10n.resetGlobalConfirmMessage) |
| 250 |
|
| 251 |
if (!iAgree) { |
| 252 |
return |
| 253 |
} |
| 254 |
|
| 255 |
$.each(api.settings.controls, function (key, ctrl) { |
| 256 |
const settingID = key.replace('_control', '') |
| 257 |
const setting = customify.config.settings[settingID] |
| 258 |
|
| 259 |
if (!_.isUndefined(setting) && !_.isUndefined(setting.default)) { |
| 260 |
apiSetSettingValue(settingID, setting.default) |
| 261 |
} |
| 262 |
}) |
| 263 |
|
| 264 |
api.previewer.save() |
| 265 |
} |
| 266 |
|
| 267 |
function onResetPanel (e) { |
| 268 |
e.preventDefault() |
| 269 |
|
| 270 |
const panelID = $(this).data('panel'), |
| 271 |
panel = api.panel(panelID), |
| 272 |
sections = panel.sections(), |
| 273 |
iAgree = confirm(customify.l10n.resetPanelConfirmMessage) |
| 274 |
|
| 275 |
if (!iAgree) { |
| 276 |
return |
| 277 |
} |
| 278 |
if (sections.length > 0) { |
| 279 |
$.each(sections, function () { |
| 280 |
const controls = this.controls() |
| 281 |
|
| 282 |
if (controls.length > 0) { |
| 283 |
$.each(controls, function (key, ctrl) { |
| 284 |
const settingID = ctrl.id.replace('_control', ''), |
| 285 |
setting = customify.config.settings[settingID] |
| 286 |
|
| 287 |
if (!_.isUndefined(setting) && !_.isUndefined(setting.default)) { |
| 288 |
apiSetSettingValue(settingID, setting.default) |
| 289 |
} |
| 290 |
}) |
| 291 |
} |
| 292 |
}) |
| 293 |
} |
| 294 |
} |
| 295 |
|
| 296 |
function onResetSection (e) { |
| 297 |
e.preventDefault() |
| 298 |
|
| 299 |
const sectionID = $(this).data('section'), |
| 300 |
section = api.section(sectionID), |
| 301 |
controls = section.controls() |
| 302 |
|
| 303 |
const iAgree = confirm(customify.l10n.resetSectionConfirmMessage) |
| 304 |
|
| 305 |
if (!iAgree) { |
| 306 |
return |
| 307 |
} |
| 308 |
|
| 309 |
if (controls.length > 0) { |
| 310 |
$.each(controls, function (key, ctrl) { |
| 311 |
const setting_id = ctrl.id.replace('_control', ''), |
| 312 |
setting = customify.config.settings[setting_id] |
| 313 |
|
| 314 |
if (!_.isUndefined(setting) && !_.isUndefined(setting.default)) { |
| 315 |
apiSetSettingValue(setting_id, setting.default) |
| 316 |
} |
| 317 |
}) |
| 318 |
} |
| 319 |
} |
| 320 |
|
| 321 |
function handleSectionTabs () { |
| 322 |
const $navs = $('.js-section-navigation') |
| 323 |
|
| 324 |
$navs.each(function () { |
| 325 |
const $nav = $(this) |
| 326 |
const $title = $nav.parents('.accordion-section-content').find('.customize-section-title') |
| 327 |
const $parent = $nav.closest('.customize-control') |
| 328 |
|
| 329 |
$nav.appendTo($title) |
| 330 |
$title.parent().addClass('has-nav') |
| 331 |
$parent.addClass('screen-reader-text') |
| 332 |
}) |
| 333 |
|
| 334 |
$('.js-section-navigation a').on('click', function (e) { |
| 335 |
e.preventDefault() |
| 336 |
|
| 337 |
const $this = $(this) |
| 338 |
const $sidebar = $this.parents('.wp-full-overlay-sidebar-content') |
| 339 |
const $parent = $this.parents('.accordion-section-content') |
| 340 |
const href = $this.attr('href') |
| 341 |
|
| 342 |
if (href !== '#') { |
| 343 |
const actionsHeight = $('#customize-header-actions').outerHeight() |
| 344 |
const titleHeight = $parent.find('.customize-section-title').outerHeight() |
| 345 |
const $target = $(href) |
| 346 |
const offset = $target.position().top |
| 347 |
|
| 348 |
$sidebar.animate({scrollTop: offset - titleHeight - actionsHeight}, 500) |
| 349 |
} |
| 350 |
}) |
| 351 |
} |
| 352 |
|
| 353 |
const getConnectedFieldsCallback = function (parentSettingData, parentSettingID) { |
| 354 |
return function (newValue, oldValue) { |
| 355 |
_.each(parentSettingData.connected_fields, function (connectedFieldData) { |
| 356 |
if (_.isUndefined(connectedFieldData) || _.isUndefined(connectedFieldData.setting_id) || !_.isString(connectedFieldData.setting_id)) { |
| 357 |
return |
| 358 |
} |
| 359 |
const setting = api(connectedFieldData.setting_id) |
| 360 |
if (_.isUndefined(setting)) { |
| 361 |
return |
| 362 |
} |
| 363 |
setting.set(newValue) |
| 364 |
}) |
| 365 |
} |
| 366 |
} |
| 367 |
|
| 368 |
const bindConnectedFields = function () { |
| 369 |
_.each(api.settings.settings, function (parentSettingData, parentSettingID) { |
| 370 |
// We don't want to handle the binding of the Style Manager settings |
| 371 |
if (typeof customify.colorPalettes !== 'undefined' |
| 372 |
&& typeof customify.colorPalettes.masterSettingIds !== 'undefined' |
| 373 |
&& _.includes(customify.colorPalettes.masterSettingIds, parentSettingID)) { |
| 374 |
return |
| 375 |
} |
| 376 |
if (typeof customify.fontPalettes !== 'undefined' |
| 377 |
&& typeof customify.fontPalettes.masterSettingIds !== 'undefined' |
| 378 |
&& _.includes(customify.fontPalettes.masterSettingIds, parentSettingID)) { |
| 379 |
return |
| 380 |
} |
| 381 |
|
| 382 |
const parent_setting = api(parentSettingID) |
| 383 |
if (typeof parentSettingData.connected_fields !== 'undefined') { |
| 384 |
customify.connectedFieldsCallbacks[parentSettingID] = getConnectedFieldsCallback(parentSettingData, parentSettingID) |
| 385 |
parent_setting.bind(customify.connectedFieldsCallbacks[parentSettingID]) |
| 386 |
} |
| 387 |
}) |
| 388 |
} |
| 389 |
|
| 390 |
/** |
| 391 |
* This function will search for all the interdependend fields and make a bound between them. |
| 392 |
* So whenever a target is changed, it will take actions to the dependent fields. |
| 393 |
* @TODO this is still written in a barbaric way, refactor when needed |
| 394 |
*/ |
| 395 |
const customifyFoldingFields = function () { |
| 396 |
|
| 397 |
if (_.isUndefined(customify.config) || _.isUndefined(customify.config.settings)) { |
| 398 |
return // bail |
| 399 |
} |
| 400 |
|
| 401 |
$.fn.reactor.defaults.compliant = function () { |
| 402 |
$(this).slideDown() |
| 403 |
$(this).find(':disabled').attr({disabled: false}) |
| 404 |
} |
| 405 |
|
| 406 |
$.fn.reactor.defaults.uncompliant = function () { |
| 407 |
$(this).slideUp() |
| 408 |
$(this).find(':enabled').attr({disabled: true}) |
| 409 |
} |
| 410 |
|
| 411 |
let IS = $.extend({}, $.fn.reactor.helpers) |
| 412 |
|
| 413 |
const bindFoldingEvents = function (parentID, field, relation) { |
| 414 |
|
| 415 |
let key = null |
| 416 |
|
| 417 |
if (_.isString(field)) { |
| 418 |
key = field |
| 419 |
} else if (!_.isUndefined(field.id)) { |
| 420 |
key = field.id |
| 421 |
} else if (_.isString(field[0])) { |
| 422 |
key = field[0] |
| 423 |
} else { |
| 424 |
return // no key, no fun |
| 425 |
} |
| 426 |
|
| 427 |
let value = 1, // by default we use 1 the most used value for checkboxes or inputs |
| 428 |
between = [0, 1] // can only be `show` or `hide` |
| 429 |
|
| 430 |
const target_key = customify.config.options_name + '[' + key + ']' |
| 431 |
const target_type = customify.config.settings[target_key].type |
| 432 |
|
| 433 |
// we support the usual syntax like a config array like `array( 'id' => $id, 'value' => $value, 'compare' => $compare )` |
| 434 |
// but we also support a non-associative array like `array( $id, $value, $compare )` |
| 435 |
if (!_.isUndefined(field.value)) { |
| 436 |
value = field.value |
| 437 |
} else if (!_.isUndefined(field[1]) && !_.isString(field[1])) { |
| 438 |
value = field[1] |
| 439 |
} |
| 440 |
|
| 441 |
if (!_.isUndefined(field.between)) { |
| 442 |
between = field.between |
| 443 |
} |
| 444 |
|
| 445 |
/** |
| 446 |
* Now for each target we have, we will bind a change event to hide or show the dependent fields |
| 447 |
*/ |
| 448 |
const target_selector = '[data-customize-setting-link="' + customify.config.options_name + '[' + key + ']"]' |
| 449 |
|
| 450 |
switch (target_type) { |
| 451 |
case 'checkbox': |
| 452 |
$(parentID).reactIf(target_selector, function () { |
| 453 |
return $(this).is(':checked') == value |
| 454 |
}) |
| 455 |
break |
| 456 |
|
| 457 |
case 'radio': |
| 458 |
case 'sm_radio': |
| 459 |
case 'sm_switch': |
| 460 |
case 'radio_image': |
| 461 |
case 'radio_html': |
| 462 |
|
| 463 |
// in case of an array of values we use the ( val in array) condition |
| 464 |
if (_.isObject(value)) { |
| 465 |
value = _.toArray(value) |
| 466 |
$(parentID).reactIf(target_selector, function () { |
| 467 |
return ( |
| 468 |
value.indexOf($(target_selector + ':checked').val()) !== -1 |
| 469 |
) |
| 470 |
}) |
| 471 |
} else { // in any other case we use a simple == comparison |
| 472 |
$(parentID).reactIf(target_selector, function () { |
| 473 |
return $(target_selector + ':checked').val() == value |
| 474 |
}) |
| 475 |
} |
| 476 |
break |
| 477 |
|
| 478 |
case 'range': |
| 479 |
const x = IS.Between(between[0], between[1]) |
| 480 |
|
| 481 |
$(parentID).reactIf(target_selector, x) |
| 482 |
break |
| 483 |
|
| 484 |
default: |
| 485 |
// in case of an array of values we use the ( val in array) condition |
| 486 |
if (_.isObject(value)) { |
| 487 |
value = _.toArray(value) |
| 488 |
$(parentID).reactIf(target_selector, function () { |
| 489 |
return ( |
| 490 |
value.indexOf($(target_selector).val()) !== -1 |
| 491 |
) |
| 492 |
}) |
| 493 |
} else { // in any other case we use a simple == comparison |
| 494 |
$(parentID).reactIf(target_selector, function () { |
| 495 |
return $(target_selector).val() == value |
| 496 |
}) |
| 497 |
} |
| 498 |
break |
| 499 |
} |
| 500 |
|
| 501 |
$(target_selector).trigger('change', ['customify']) |
| 502 |
$('.reactor').trigger('change.reactor') // triggers all events on load |
| 503 |
} |
| 504 |
|
| 505 |
$.each(customify.config.settings, function (id, field) { |
| 506 |
/** |
| 507 |
* Here we have the id of the fields. but we know for sure that we just need his parent selector |
| 508 |
* So we just create it |
| 509 |
*/ |
| 510 |
let parentID = id.replace('[', '-') |
| 511 |
parentID = parentID.replace(']', '') |
| 512 |
parentID = '#customize-control-' + parentID + '_control' |
| 513 |
|
| 514 |
// get only the fields that have a 'show_if' property |
| 515 |
if (field.hasOwnProperty('show_if')) { |
| 516 |
let relation = 'AND' |
| 517 |
|
| 518 |
if (!_.isUndefined(field.show_if.relation)) { |
| 519 |
relation = field.show_if.relation |
| 520 |
// remove the relation property, we need the config to be array based only |
| 521 |
delete field.show_if.relation |
| 522 |
} |
| 523 |
|
| 524 |
/** |
| 525 |
* The 'show_if' can be a simple array with one target like: [ id, value, comparison, action ] |
| 526 |
* Or it could be an array of multiple targets and we need to process both cases |
| 527 |
*/ |
| 528 |
|
| 529 |
if (!_.isUndefined(field.show_if.id)) { |
| 530 |
bindFoldingEvents(parentID, field.show_if, relation) |
| 531 |
} else if (_.isObject(field.show_if)) { |
| 532 |
$.each(field.show_if, function (i, j) { |
| 533 |
bindFoldingEvents(parentID, j, relation) |
| 534 |
}) |
| 535 |
} |
| 536 |
} |
| 537 |
}) |
| 538 |
} |
| 539 |
|
| 540 |
/** |
| 541 |
* Set a setting value. |
| 542 |
* |
| 543 |
* Mostly used for resetting settings (via the reset buttons) but also for the preset (legacy) field. |
| 544 |
* |
| 545 |
* @param settingID |
| 546 |
* @param value |
| 547 |
*/ |
| 548 |
const apiSetSettingValue = function (settingID, value) { |
| 549 |
const setting = api(settingID), |
| 550 |
field = $('[data-customize-setting-link="' + settingID + '"]'), |
| 551 |
fieldClass = $(field).parent().attr('class') |
| 552 |
|
| 553 |
if (!_.isUndefined(fieldClass) && fieldClass === 'font-options__wrapper') { |
| 554 |
|
| 555 |
// if the value is a simple string it must be the font family |
| 556 |
if (_.isString(value)) { |
| 557 |
setting.set({'font_family': value}) |
| 558 |
} else if (_.isObject(value)) { |
| 559 |
const standardValue = {} |
| 560 |
// We will process each font property and update it |
| 561 |
_.each(value, function (val, key) { |
| 562 |
// We need to map the keys to the data attributes we are using - I know :( |
| 563 |
let mappedKey = key |
| 564 |
switch (key) { |
| 565 |
case 'font-family': |
| 566 |
mappedKey = 'font_family' |
| 567 |
break |
| 568 |
case 'font-size': |
| 569 |
mappedKey = 'font_size' |
| 570 |
break |
| 571 |
case 'font-weight': |
| 572 |
mappedKey = 'font_variant' |
| 573 |
break |
| 574 |
case 'letter-spacing': |
| 575 |
mappedKey = 'letter_spacing' |
| 576 |
break |
| 577 |
case 'text-transform': |
| 578 |
mappedKey = 'text_transform' |
| 579 |
break |
| 580 |
default: |
| 581 |
break |
| 582 |
} |
| 583 |
|
| 584 |
standardValue[mappedKey] = val |
| 585 |
}) |
| 586 |
|
| 587 |
setting.set(standardValue) |
| 588 |
} |
| 589 |
} else { |
| 590 |
setting.set(value) |
| 591 |
} |
| 592 |
} |
| 593 |
|
| 594 |
const handlePreviewIframe = function () { |
| 595 |
api.previewer.bind('synced', function () { |
| 596 |
scaleIframe() |
| 597 |
|
| 598 |
api.previewedDevice.bind(scaleIframe) |
| 599 |
$window.on('resize', scaleIframe) |
| 600 |
}) |
| 601 |
|
| 602 |
$('.collapse-sidebar').on('click', function () { |
| 603 |
setTimeout(scaleIframe, 300) |
| 604 |
}) |
| 605 |
} |
| 606 |
|
| 607 |
const scaleIframe = function () { |
| 608 |
const $previewIframe = $('.wp-full-overlay') |
| 609 |
|
| 610 |
// remove CSS properties that may have been previously added |
| 611 |
$previewIframe.find('iframe').css({ |
| 612 |
width: '', |
| 613 |
height: '', |
| 614 |
transformOrigin: '', |
| 615 |
transform: '' |
| 616 |
}) |
| 617 |
|
| 618 |
// scaling of the site preview should be done only in desktop preview mode |
| 619 |
if (api.previewedDevice.get() !== 'desktop') { |
| 620 |
return |
| 621 |
} |
| 622 |
|
| 623 |
const iframeWidth = $previewIframe.width() |
| 624 |
const windowWidth = $window.width() |
| 625 |
const windowHeight = $window.height() |
| 626 |
|
| 627 |
// get the ratio between the site preview and actual browser width |
| 628 |
const scale = windowWidth / iframeWidth |
| 629 |
|
| 630 |
// for an accurate preview at resolutions where media queries may intervene |
| 631 |
// increase the width of the iframe and use CSS transforms to scale it back down |
| 632 |
if (iframeWidth > 720 && iframeWidth < 1100) { |
| 633 |
$previewIframe.find('iframe').css({ |
| 634 |
width: iframeWidth * scale, |
| 635 |
height: windowHeight * scale, |
| 636 |
transformOrigin: 'left top', |
| 637 |
transform: 'scale(' + 1 / scale + ')' |
| 638 |
}) |
| 639 |
} |
| 640 |
} |
| 641 |
|
| 642 |
/** Modules **/ |
| 643 |
|
| 644 |
const customifyBackgroundJsControl = ( |
| 645 |
function () { |
| 646 |
'use strict' |
| 647 |
|
| 648 |
function init () { |
| 649 |
// Upload media button |
| 650 |
$('.customize-control-custom_background .background_upload_button').unbind().on('click', function (event) { |
| 651 |
addImage(event, $(this).parents('.customize-control-custom_background:first')) |
| 652 |
}) |
| 653 |
|
| 654 |
// Remove the image button |
| 655 |
$('.customize-control-custom_background .remove-image, .customize-control-custom_background .remove-file').unbind('click').on('click', function (e) { |
| 656 |
removeImage($(this).parents('.customize-control-custom_background:first')) |
| 657 |
}) |
| 658 |
} |
| 659 |
|
| 660 |
// Add a file via the wp.media function |
| 661 |
function addImage (event, selector) { |
| 662 |
// Stop this from propagating. |
| 663 |
event.preventDefault() |
| 664 |
|
| 665 |
let frame |
| 666 |
const $thisElement = $(this) |
| 667 |
|
| 668 |
// If the media frame already exists, reopen it. |
| 669 |
if (frame) { |
| 670 |
frame.open() |
| 671 |
return |
| 672 |
} |
| 673 |
|
| 674 |
// Create the media frame. |
| 675 |
frame = wp.media({ |
| 676 |
multiple: false, |
| 677 |
library: { |
| 678 |
//type: 'image' //Only allow images |
| 679 |
}, |
| 680 |
// Set the title of the modal. |
| 681 |
title: $thisElement.data('choose'), |
| 682 |
|
| 683 |
// Customize the submit button. |
| 684 |
button: { |
| 685 |
// Set the text of the button. |
| 686 |
text: $thisElement.data('update') |
| 687 |
// Tell the button not to close the modal, since we're |
| 688 |
// going to refresh the page when the image is selected. |
| 689 |
} |
| 690 |
}) |
| 691 |
|
| 692 |
// When an image is selected, run a callback. |
| 693 |
frame.on('select', function () { |
| 694 |
// Grab the selected attachment. |
| 695 |
const attachment = frame.state().get('selection').first() |
| 696 |
frame.close() |
| 697 |
|
| 698 |
if (attachment.attributes.type !== 'image') { |
| 699 |
return |
| 700 |
} |
| 701 |
|
| 702 |
selector.find('.customify_background_input.background-image').val(attachment.attributes.url) |
| 703 |
|
| 704 |
selector.find('.upload').attr('value', attachment.attributes.url) |
| 705 |
selector.find('.upload-id').attr('value', attachment.attributes.id) |
| 706 |
selector.find('.upload-height').attr('value', attachment.attributes.height) |
| 707 |
selector.find('.upload-width').attr('value', attachment.attributes.width) |
| 708 |
|
| 709 |
let thumbSrc = attachment.attributes.url |
| 710 |
if (!_.isUndefined(attachment.attributes.sizes) && !_.isUndefined(attachment.attributes.sizes.thumbnail)) { |
| 711 |
thumbSrc = attachment.attributes.sizes.thumbnail.url |
| 712 |
} else if (!_.isUndefined(attachment.attributes.sizes)) { |
| 713 |
let height = attachment.attributes.height |
| 714 |
for (let key in attachment.attributes.sizes) { |
| 715 |
const object = attachment.attributes.sizes[key] |
| 716 |
if (object.height < height) { |
| 717 |
height = object.height |
| 718 |
thumbSrc = object.url |
| 719 |
} |
| 720 |
} |
| 721 |
} else { |
| 722 |
thumbSrc = attachment.attributes.icon |
| 723 |
} |
| 724 |
|
| 725 |
if (!selector.find('.upload').hasClass('noPreview')) { |
| 726 |
selector.find('.preview_screenshot').empty().hide().append('<img class="preview_image" src="' + thumbSrc + '">').slideDown('fast') |
| 727 |
} |
| 728 |
selector.find('.remove-image').removeClass('hide') // Show "Remove" button |
| 729 |
selector.find('.customify_background_select').removeClass('hide') // Show background selects |
| 730 |
|
| 731 |
updateData(selector) |
| 732 |
}) |
| 733 |
|
| 734 |
// Finally, open the modal. |
| 735 |
frame.open() |
| 736 |
} |
| 737 |
|
| 738 |
// Update the background data |
| 739 |
function updateData (selector) { |
| 740 |
|
| 741 |
let $parent = selector.parents('.customize-control-custom_background:first') |
| 742 |
|
| 743 |
if (selector.hasClass('customize-control-custom_background')) { |
| 744 |
$parent = selector |
| 745 |
} |
| 746 |
|
| 747 |
if ($parent.length > 0) { |
| 748 |
$parent = $($parent[0]) |
| 749 |
} else { |
| 750 |
return |
| 751 |
} |
| 752 |
|
| 753 |
const settingID = $parent.find('.button.background_upload_button').data('setting_id'), |
| 754 |
setting = api.instance(settingID) |
| 755 |
|
| 756 |
const background_data = {} |
| 757 |
|
| 758 |
$parent.find('.customify_background_select, .customify_background_input').each(function () { |
| 759 |
let data = $(this).serializeArray()[0] |
| 760 |
if (data && data.name.indexOf('[background-') !== -1) { |
| 761 |
background_data[$(this).data('select_name')] = data.value |
| 762 |
} |
| 763 |
}) |
| 764 |
|
| 765 |
background_data.media = {} |
| 766 |
background_data.media.id = $parent.find('.upload-id').val() |
| 767 |
background_data.media.height = $parent.find('.upload-height').val() |
| 768 |
background_data.media.width = $parent.find('.upload-width').val() |
| 769 |
background_data.media.thumbnail = $parent.find('.upload-thumbnail').val() |
| 770 |
|
| 771 |
setting.set(background_data) |
| 772 |
} |
| 773 |
|
| 774 |
// Update the background preview |
| 775 |
function removeImage (parent) { |
| 776 |
const selector = parent.find('.upload_button_div') |
| 777 |
// This shouldn't have been run... |
| 778 |
if (!selector.find('.remove-image').addClass('hide')) { |
| 779 |
return |
| 780 |
} |
| 781 |
|
| 782 |
// Hide "Remove" button. |
| 783 |
selector.find('.remove-image').addClass('hide') |
| 784 |
parent.find('.customify_background_select').addClass('hide') |
| 785 |
|
| 786 |
parent.find('.upload').val(null) |
| 787 |
parent.find('.upload-id').val(null) |
| 788 |
parent.find('.upload-height').val(null) |
| 789 |
parent.find('.upload-width').val(null) |
| 790 |
parent.find('.customify_background_input.background-image').val(null) |
| 791 |
|
| 792 |
// Hide the screenshot |
| 793 |
parent.find('.preview_screenshot').slideUp() |
| 794 |
|
| 795 |
updateData(parent) |
| 796 |
} |
| 797 |
|
| 798 |
return { |
| 799 |
init: init |
| 800 |
} |
| 801 |
} |
| 802 |
)(jQuery) |
| 803 |
|
| 804 |
/** HELPERS **/ |
| 805 |
|
| 806 |
const getUrlVar = function (name) { |
| 807 |
const vars = [] |
| 808 |
let hash |
| 809 |
const hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&') |
| 810 |
|
| 811 |
for (let i = 0; i < hashes.length; i++) { |
| 812 |
hash = hashes[i].split('=') |
| 813 |
|
| 814 |
vars.push(hash[0]) |
| 815 |
vars[hash[0]] = hash[1] |
| 816 |
} |
| 817 |
|
| 818 |
if (!_.isUndefined(vars[name])) { |
| 819 |
return vars[name] |
| 820 |
} |
| 821 |
return false |
| 822 |
} |
| 823 |
})(jQuery, customify, wp) |
| 824 |
|