PluginProbe
Customify / 2.7.0
Customify v2.7.0
2.10.9 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.7.1 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.6.0 1.6.0.1 1.6.5 1.7.0 1.7.1 All 77 releases
customify / js / customizer / font-fields.js

font-fields.js in Customify 2.7.0, at js/customizer/font-fields.js

695 lines 25.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /** @namespace customify */
2 window.customify = window.customify || parent.customify || {};
3
4 // This is for the Customizer Font control
5 (function ($, customify, wp) {
6
7 /**
8 * Expose the API publicly on window.customify.fontFields
9 *
10 * @namespace customify.fontFields
11 */
12 if ( typeof customify.fontFields === 'undefined' ) {
13 customify.fontFields = {}
14 }
15 _.extend( customify.fontFields, function () {
16 const wrapperSelector = '.font-options__wrapper',
17 valueHolderSelector = '.customify_font_values',
18 fontFamilySelector = '.customify_font_family',
19 fontVariantSelector = '.customify_font_weight',
20 fontSubsetsSelector = '.customify_font_subsets',
21 fontHeadTitleSelector = '.font-options__head .font-options__font-title'
22
23 let familyPlaceholderText ,
24 variantAutoText, // This is for the empty value.
25 subsetPlaceholderText
26
27 const api = wp.customize
28
29 // We will use this to remember that we are self-updating the field from the subfields.
30 // We will save this info for each setting ID.
31 const updatingValue = {},
32 loadingValue = {}
33
34 const init = function () {
35 familyPlaceholderText = customify.l10n.fonts.familyPlaceholderText
36 variantAutoText = customify.l10n.fonts.variantAutoText
37 subsetPlaceholderText = customify.l10n.fonts.subsetPlaceholderText
38
39 const $fontFamilyFields = $(fontFamilySelector)
40
41 // Add the Google Fonts opts to each control.
42 if (typeof api.settings['google_fonts_opts'] !== 'undefined') {
43 $fontFamilyFields.each(function (i, el) {
44 const googleOptionsPlaceholder = $(el).find('.google-fonts-opts-placeholder').first()
45 if (googleOptionsPlaceholder) {
46 // Replace the placeholder with the HTML for the Google fonts select options.
47 googleOptionsPlaceholder.replaceWith(api.settings['google_fonts_opts'])
48
49 // The active font family might be a Google font so we need to set the current value after we've added the options.
50 const activeFontFamily = $(el).data('active_font_family')
51 if (typeof activeFontFamily !== 'undefined') {
52 $(el).val(activeFontFamily)
53 }
54 }
55 })
56 }
57
58 // Initialize the select2 field for the font family
59 $fontFamilyFields.select2({
60 placeholder: familyPlaceholderText
61 })
62
63 // We only need to bind to the original select since select2 triggers the event for this one when changed.
64 $fontFamilyFields.on('change', function (event, who) {
65 const newFontFamily = event.target.value,
66 wrapper = $(event.target).closest(wrapperSelector),
67 settingID = $(wrapper.children(valueHolderSelector)).data('customize-setting-link'),
68 setting = api(settingID)
69
70 // Get the new font details
71 const newFontDetails = getFontDetails(newFontFamily)
72
73 // Update the font field head title (with the new font family name).
74 updateFontHeadTitle(newFontDetails, wrapper)
75
76 // Update the variant subfield with the new options given by the selected font family.
77 updateVariantField(newFontDetails, wrapper)
78
79 // Update the subset subfield with the new options given by the selected font family.
80 updateSubsetField(newFontDetails, wrapper, setting)
81
82 if (typeof who !== 'undefined' && who === 'customify') {
83 // The change was triggered programmatically by Customify.
84 // No need to self-update the value.
85 } else {
86 // Mark this input as touched by the user.
87 $(event.target).data('touched', true)
88
89 // Serialize subfield values and refresh the fonts in the preview window.
90 selfUpdateValue(wrapper, settingID)
91 }
92 })
93
94 // Handle the reverse value direction, when the customize setting is updated and the subfields need to update their values.
95 $fontFamilyFields.each(function (i, el) {
96 const wrapper = $(el).closest(wrapperSelector),
97 settingID = $(wrapper.children(valueHolderSelector)).data('customize-setting-link'),
98 setting = api(settingID)
99
100 setting.bind(function (newValue, oldValue) {
101 if (!updatingValue[this.id]) {
102 loadFontValue(wrapper, newValue, this.id)
103 }
104 })
105 })
106
107 // Initialize the select2 field for the font variant
108 initSubfield($(fontVariantSelector), true)
109
110 // Initialize the select2 field for the font subsets
111 initSubfield($(fontSubsetsSelector), true, subsetPlaceholderText)
112
113 // Initialize all the regular selects in the font subfields
114 initSubfield($fontFamilyFields.parents(wrapperSelector).find('select').not('select[class*=\' select2\'],select[class^=\'select2\']'), false);
115
116 // Initialize the all the range fields in the font subfields
117 initSubfield($fontFamilyFields.parents(wrapperSelector).find('input[type=range]'), false);
118
119 handleFontPopupToggle()
120 }
121
122 const initSubfield = function (subfieldList, select2 = false, select2Placeholder = '') {
123 if (!subfieldList.length) {
124 return
125 }
126 // Mark these as not touched by the user.
127 $(subfieldList).data('touched', false)
128
129 $(subfieldList).on('input change', function (event, who) {
130 if (typeof who !== 'undefined' && who === 'customify') {
131 // The change was triggered programmatically by Customify.
132 // No need to self-update the value.
133 } else {
134 const wrapper = $(event.target).closest(wrapperSelector),
135 settingID = $(wrapper.children(valueHolderSelector)).data('customize-setting-link')
136
137 // Mark this input as touched by the user.
138 $(event.target).data('touched', true)
139
140 // Gather subfield values and trigger refresh of the fonts in the preview window.
141 selfUpdateValue(wrapper, settingID)
142 }
143 })
144
145 // If we've been instructed, initialize a select2.
146 if (true === select2) {
147 const select2Args = {}
148
149 if (!_.isEmpty(select2Placeholder)) {
150 select2Args['placeholder'] = select2Placeholder
151 }
152
153 $(subfieldList).select2(select2Args)
154 }
155 }
156
157 const handleFontPopupToggle = function () {
158 const $allFontCheckboxes = $('#customize-controls .js-font-option-toggle')
159
160 // Close all other font fields popups when opening a font field popup.
161 $allFontCheckboxes.on('click', function () {
162 const $checkbox = $(this)
163 if ($checkbox.prop('checked') === true) {
164 $allFontCheckboxes.not($checkbox).prop('checked', false)
165 }
166 })
167
168 // Make sure that all fonts popups are closed when backing away from a panel or section.
169 // @todo This doesn't catch backing with ESC key. For that we should hook on Customizer section and panel events ('collapsed').
170 $('#customize-controls .customize-panel-back, #customize-controls .customize-section-back').on('click', function() {
171 $allFontCheckboxes.prop('checked', false)
172 })
173 }
174
175 /**
176 * Update the title of the font field (the field head) with the new font family name.
177 *
178 * @param newFontDetails
179 * @param wrapper
180 */
181 const updateFontHeadTitle = function (newFontDetails, wrapper) {
182 const fontTitleElement = wrapper.find(fontHeadTitleSelector)
183
184 let fontFamilyDisplay = newFontDetails.family
185 if (typeof newFontDetails.family_display !== 'undefined') {
186 fontFamilyDisplay = newFontDetails.family_display
187 }
188
189 $(fontTitleElement).html(fontFamilyDisplay)
190 }
191
192 /**
193 * This function updates the data in font weight selector from the given <option> element
194 *
195 * @param newFontDetails
196 * @param wrapper
197 */
198 const updateVariantField = function (newFontDetails, wrapper) {
199 const variants = typeof newFontDetails.variants !== 'undefined' ? newFontDetails.variants : [],
200 fontVariantInput = wrapper.find(fontVariantSelector),
201 selectedVariant = fontVariantInput.val() ? fontVariantInput.val() : '',
202 newVariants = []
203
204 // We clear everything about this subfield.
205 fontVariantInput.val(null).empty()
206 if (fontVariantInput.hasClass("select2-hidden-accessible")) {
207 fontVariantInput.select2('destroy')
208 }
209
210 // Mark this input as not touched by the user.
211 fontVariantInput.data('touched', false)
212
213 if (typeof variants === 'undefined' || Object.keys(variants).length < 2) {
214 fontVariantInput.parent().hide()
215 fontVariantInput.parent().prev('label').hide()
216 // Mark this input as disabled.
217 fontVariantInput.data('disabled', true)
218 return
219 }
220
221 // Initialize the options with an empty one.
222 newVariants.push({
223 'id': '',
224 'text': variantAutoText
225 })
226
227 // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
228 $.each(variants, function (index, variant) {
229 let newVariant = {
230 'id': variant, // This is the option value.
231 'text': variant
232 }
233
234 // Leave the comparison loose.
235 if (selectedVariant == variant) {
236 newVariant.selected = true
237 }
238
239 newVariants.push(newVariant)
240 })
241
242 // Only reinitialize the select2.
243 // No need to rebind on change or on input since those are still bound to the original HTML element.
244 fontVariantInput.select2({
245 data: newVariants
246 })
247
248 fontVariantInput.parent().show()
249 fontVariantInput.parent().prev('label').show()
250 // Mark this input as enabled.
251 fontVariantInput.data('disabled', false)
252 }
253
254 /**
255 * This function updates the data in font subset selector from the given <option> element
256 * @param newFontDetails
257 * @param wrapper
258 * @param setting
259 */
260 const updateSubsetField = function (newFontDetails, wrapper, setting) {
261 const subsets = typeof newFontDetails.subsets !== 'undefined' ? newFontDetails.subsets : [],
262 fontSubsetsInput = wrapper.find(fontSubsetsSelector),
263 newSubsets = []
264
265 // We clear everything about this subfield.
266 fontSubsetsInput.val(null).empty()
267 if (fontSubsetsInput.hasClass("select2-hidden-accessible")) {
268 fontSubsetsInput.select2('destroy')
269 }
270
271 // Mark this input as not touched by the user.
272 fontSubsetsInput.data('touched', false)
273
274 if (typeof subsets === 'undefined' || Object.keys(subsets).length < 2) {
275 fontSubsetsInput.parent().hide()
276 fontSubsetsInput.parent().prev('label').hide()
277 // Mark this input as disabled.
278 fontSubsetsInput.data('disabled', true)
279 return
280 }
281
282 // Attempt to keep (some of) the previously selected subsets, depending on what the new font supports.
283 const currentFontValue = setting()
284 let selectedSubsets = []
285 if (!_.isUndefined(currentFontValue.selected_subsets) && !_.isEmpty(currentFontValue.selected_subsets)) {
286 selectedSubsets = currentFontValue.selected_subsets
287 // Make sure it is an array
288 if (!Array.isArray(selectedSubsets)) {
289 selectedSubsets = Object.keys(selectedSubsets).map(function (key) {
290 return selectedSubsets[key]
291 })
292 }
293 }
294
295 // we need to turn the data array into a specific form like [{id:"id", text:"Text"}]
296 $.each(subsets, function (index, subset) {
297 // We want to skip the 'latin' subset since that is loaded by default.
298 if ('latin' === subset) {
299 return
300 }
301
302 const newSubset = {
303 'id': subset,
304 'text': subset
305 }
306
307 if (selectedSubsets.indexOf(subset) !== -1) {
308 newSubset.selected = true
309 }
310
311 newSubsets.push(newSubset)
312 })
313
314 // Only reinitialize the select2.
315 // No need to rebind on change or on input since those are still bound to the original HTML element.
316 fontSubsetsInput.select2({
317 data: newSubsets,
318 placeholder: subsetPlaceholderText
319 })
320
321 fontSubsetsInput.parent().show()
322 fontSubsetsInput.parent().prev('label').show()
323 // Mark this input as enabled.
324 fontSubsetsInput.data('disabled', false)
325 }
326
327 /**
328 * Gather the value for our entire font field and save it in the setting.
329 */
330 const selfUpdateValue = function (wrapper, settingID) {
331 // If we are already self-updating this and we haven't finished, we need to stop here to prevent infinite loops
332 // This call might have come from a subfield detecting the change thus triggering a further selfUpdateValue()
333 if (true === updatingValue[settingID]) {
334 return
335 }
336
337 // If we are loading this setting value and haven't finished,
338 // there is no point in updating it as this would cause infinite loops.
339 if (true === loadingValue[settingID]) {
340 return
341 }
342
343 // Mark the fact that we are self-updating the field value
344 updatingValue[settingID] = true
345
346 const optionsList = wrapper.find('.font-options__options-list'),
347 inputs = optionsList.find('[data-value_entry]'),
348 setting = api(settingID),
349 oldValue = setting(),
350 newFontData = _.isEmpty(oldValue) ? {} : $.extend(true, {}, oldValue)
351
352 inputs.each(function (key, input) {
353 const $input = $(input)
354 const valueEntry = $input.data('value_entry')
355 let value = $input.val()
356
357 // We only pick up subfields values that have been touched by the user, that are enabled (visible) or values that are missing in the oldValue.
358 if (_.isUndefined(valueEntry) || $input.data('disabled') || (!$input.data('touched') && !_.isUndefined(newFontData[valueEntry]))) {
359 return
360 }
361
362 if ('font_family' === valueEntry) {
363 // Get the src of the selected option.
364 const src = $(input.options[input.selectedIndex]).data('src')
365
366 if (src) {
367 newFontData['src'] = src
368 } else {
369 delete newFontData['src']
370 }
371 }
372
373 if (!_.isUndefined(value) && !_.isNull(value) && value !== '') {
374 if (_.includes(['letter_spacing', 'line_height', 'font_size'], valueEntry)) {
375 // Standardize the value.
376 value = standardizeNumericalValue(value, input, false)
377 }
378
379 newFontData[valueEntry] = value
380 } else {
381 delete newFontData[valueEntry]
382 }
383 })
384
385 // We don't need to store font variants or subsets list in the value
386 // since we will get those from the global font details.
387 delete newFontData['variants']
388 delete newFontData['subsets']
389
390 // We need to make sure that we don't "use" any variants or subsets not supported by the new font (values passed over from the old value).
391 // Get the new font details
392 const newFontDetails = getFontDetails(newFontData['font_family'])
393 // Check the font variant
394 if (typeof newFontData['font_variant'] !== 'undefined' && typeof newFontDetails.variants !== 'undefined' && Object.keys(newFontDetails.variants).length > 0) {
395 if (!_.includes(newFontDetails.variants, newFontData['font_variant'])) {
396 // The new font doesn't have this variant. Nor should the value.
397 delete newFontData['font_variant']
398 }
399 } else {
400 // The new font has no variants. Nor should the value.
401 delete newFontData['font_variant']
402 }
403 // Check the subsets
404 if (typeof newFontData['selected_subsets'] !== 'undefined' && typeof newFontDetails.subsets !== 'undefined' && Object.keys(newFontDetails.subsets).length > 0) {
405 // We will use the intersection between the font's subsets and the selected subsets.
406 newFontData['selected_subsets'] = _.intersection(newFontData['selected_subsets'],newFontDetails.subsets)
407 } else {
408 // The new font has no subsets. Nor should the value.
409 delete newFontData['selected_subsets']
410 }
411
412 // Update the Customizer setting value.
413 setting.set(newFontData)
414
415 // Finished with the field value self-updating.
416 updatingValue[settingID] = false
417 }
418
419 /**
420 * This function is a reverse of selfUpdateValue(), initializing the entire font field controls
421 * based on the setting value.
422 */
423 const loadFontValue = function (wrapper, value, settingID) {
424 // If we are already loading this setting value and haven't finished, there is no point in starting again.
425 if (true === loadingValue[settingID]) {
426 return
427 }
428
429 // Mark the fact that we are loading the field value
430 loadingValue[settingID] = true
431
432 const optionsList = $(wrapper).find('.font-options__options-list'),
433 inputs = optionsList.find('[data-value_entry]')
434
435 inputs.each(function (key, input) {
436 const $input = $(input)
437 const valueEntry = $input.data('value_entry')
438
439 // In the case of select2, only the original selects have the data field, thus excluding select2 created select DOM elements
440 if (typeof valueEntry === 'undefined' || valueEntry === '' || typeof value[valueEntry] === 'undefined') {
441 return
442 }
443
444 // We will do this only for numerical sub-fields.
445 if (_.includes(['letter_spacing', 'line_height', 'font_size'], valueEntry)) {
446 const subfieldValue = standardizeNumericalValue(value[valueEntry], input)
447
448 // Make sure that the unit and value_unit attributes are in place.
449 if (subfieldValue.unit !== '') {
450 $input.data('value_unit', subfieldValue.unit)
451 if (_.isEmpty($input.attr('unit'))) {
452 $input.attr('unit', subfieldValue.unit)
453 }
454 }
455
456 // If the field unit and value unit differ, we have some conversion to do.
457 // We will convert the received value to the appropriate unit declared by the input.
458 // We will use a guessed base size of 16px. Not an exact conversion, but it will have to do.
459 const baseSize = 16
460 const subfieldUnit = $input.attr('unit').trim().toLowerCase()
461 const subfieldValueUnit = $input.data('value_unit').trim().toLowerCase()
462 // The comparison is intentionally loose.
463 if (subfieldUnit != subfieldValueUnit) {
464 if (_.includes(['em', 'rem'], subfieldValueUnit) && 'px' === subfieldUnit) {
465 // We will have to multiply the value.
466 subfieldValue.value = round(subfieldValue.value * baseSize, customify.fonts.floatPrecision)
467 } else if (_.includes(['em', 'rem'], subfieldUnit) && 'px' === subfieldValueUnit) {
468 // We will have to divide the value.
469 subfieldValue.value = round(subfieldValue.value / baseSize, customify.fonts.floatPrecision)
470 }
471 }
472
473 // If this field has a min/max attribute we need to make sure that those attributes allow for the value we are trying to impose.
474 if ($input.attr('min') && $input.attr('min') > subfieldValue.value) {
475 $input.attr('min', subfieldValue.value)
476 }
477 if ($input.attr('max') && $input.attr('max') < subfieldValue.value) {
478 $input.attr('max', subfieldValue.value)
479 }
480
481 $input.val(subfieldValue.value)
482 } else {
483 $input.val(value[valueEntry])
484 }
485
486 // Mark this input as not touched by the user.
487 $input.data('touched', false)
488
489 $input.trigger('change', ['customify'])
490 })
491
492 // Finished with the field value loading.
493 loadingValue[settingID] = false
494 }
495
496 /**
497 * Given a value we will standardize it to an array with 'value' and 'unit'.
498 *
499 * This is a mirror logic of the server-side one from Customify_Fonts_Global::standardizeNumericalValue()
500 *
501 * @param value
502 * @param input Optional. The input this value was extracted from
503 * @param valueFirst Optional. Whether to give higher priority to value related data, or to input related one.
504 */
505 const standardizeNumericalValue = function (value, input = false, valueFirst = true) {
506 const standardValue = {value: false, unit: false}
507
508 if (_.includes(['','false',false], value)) {
509 return standardValue
510 }
511
512 if (!isNaN(value)) {
513 standardValue.value = value
514 } else if (typeof value.value !== 'undefined') {
515 standardValue.value = value.value
516 if (typeof value.unit !== 'undefined') {
517 standardValue.unit = value.unit
518 }
519 } else if (typeof value[0] !== 'undefined') {
520 standardValue.value = value[0]
521 if (typeof value[1] !== 'undefined') {
522 standardValue.unit = value[1]
523 }
524 } else if (typeof value === 'string') {
525 // We will get everything in front that is a valid part of a number (float including).
526 const matches = value.match(/^([\d.\-+]+)(.+)/i)
527 if (matches !== null && typeof matches[1] !== 'undefined') {
528 standardValue.value = matches[1]
529 if (!_.isEmpty(matches[2])) {
530 standardValue.unit = matches[2]
531 }
532 } else {
533 // If we could not extract anything useful we will trust the developer and leave it like that.
534 standardValue.value = value
535 }
536 }
537
538 if (false !== input && (false === standardValue.unit || _.isEmpty(standardValue.unit))) {
539 // If we are given an input, we will attempt to extract the unit from its attributes.
540 let fallbackInputUnit = ''
541 const $input = $(input)
542
543 if (valueFirst) {
544 if (!_.isEmpty($input.data('value_unit'))) {
545 fallbackInputUnit = $input.data('value_unit')
546 } else if (!_.isEmpty($input.attr('unit'))) {
547 fallbackInputUnit = $input.attr('unit')
548 }
549 } else {
550 if (!_.isEmpty($input.attr('unit'))) {
551 fallbackInputUnit = $input.attr('unit')
552 } else if (!_.isEmpty($input.data('value_unit'))) {
553 fallbackInputUnit = $input.data('value_unit')
554 }
555 }
556 standardValue.unit = fallbackInputUnit
557 }
558
559 return standardValue
560 }
561
562 const determineFontType = function (fontFamily) {
563 // The default is a standard font (aka no special loading or processing).
564 let fontType = 'std_font'
565
566 // We will follow a stack in the following order: theme fonts, cloud fonts, standard fonts, Google fonts.
567 if (typeof customify.fonts.theme_fonts[fontFamily] !== 'undefined') {
568 fontType = 'theme_font'
569 } else if (typeof customify.fonts.cloud_fonts[fontFamily] !== 'undefined') {
570 fontType = 'cloud_font'
571 } else if (typeof customify.fonts.google_fonts[fontFamily] !== 'undefined') {
572 fontType = 'google_font'
573 }
574
575 return fontType
576 }
577
578 const getFontDetails = function (fontFamily, fontType = false) {
579 if (false === fontType) {
580 // We will determine the font type based on font family.
581 fontType = determineFontType(fontFamily)
582 }
583
584 switch (fontType) {
585 case 'theme_font':
586 return customify.fonts.theme_fonts[fontFamily]
587 break
588 case 'cloud_font':
589 return customify.fonts.cloud_fonts[fontFamily]
590 break
591 case 'google_font':
592 return customify.fonts.google_fonts[fontFamily]
593 break
594 case 'std_font':
595 if (typeof customify.fonts.std_fonts[fontFamily] !== 'undefined') {
596 return customify.fonts.std_fonts[fontFamily]
597 }
598 break
599 default:
600 }
601
602 return false
603 }
604
605 /**
606 * Will convert an array of CSS like variants into their FVD equivalents. Web Font Loader expects this format.
607 * @link https://github.com/typekit/fvd
608 */
609 const convertFontVariantToFVD = function (variant) {
610 variant = String(variant)
611
612 let fontStyle = 'n' // normal
613 if (-1 !== variant.indexOf('italic')) {
614 fontStyle = 'i'
615 variant = variant.replace('italic', '')
616 } else if (-1 !== variant.indexOf('oblique')) {
617 fontStyle = 'o'
618 variant = variant.replace('oblique', '')
619 }
620
621 let fontWeight
622
623 // The equivalence:
624 //
625 // 1: 100
626 // 2: 200
627 // 3: 300
628 // 4: 400 (default, also recognized as 'normal')
629 // 5: 500
630 // 6: 600
631 // 7: 700 (also recognized as 'bold')
632 // 8: 800
633 // 9: 900
634
635 switch (variant) {
636 case '100':
637 fontWeight = '1'
638 break
639 case '200':
640 fontWeight = '2'
641 break
642 case '300':
643 fontWeight = '3'
644 break
645 case '500':
646 fontWeight = '5'
647 break
648 case '600':
649 fontWeight = '6'
650 break
651 case '700':
652 case 'bold':
653 fontWeight = '7'
654 break
655 case '800':
656 fontWeight = '8'
657 break
658 case '900':
659 fontWeight = '9'
660 break
661 default:
662 fontWeight = '4'
663 break
664 }
665
666 return fontStyle + fontWeight
667 }
668
669 /**
670 * Round a number to a precision, specified in number of decimal places
671 *
672 * @param {number} number - The number to round
673 * @param {number} precision - The number of decimal places to round to:
674 * > 0 means decimals, < 0 means powers of 10
675 *
676 *
677 * @return {number} - The number, rounded
678 */
679 const round = function (number, precision) {
680 const factor = Math.pow(10, precision)
681 return Math.round(number * factor) / factor;
682 }
683
684 return {
685 init: init,
686 selfUpdateValue: selfUpdateValue,
687 standardizeNumericalValue: standardizeNumericalValue,
688 determineFontType: determineFontType,
689 getFontDetails: getFontDetails,
690 convertFontVariantToFVD: convertFontVariantToFVD,
691 round: round,
692 }
693 }() )
694 })(jQuery, customify, wp)
695