PluginProbe
Customify / trunk
Customify vtrunk
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.js

customizer.js in Customify trunk, at js/customizer.js

824 lines 26.0 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 (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