PluginProbe
Customify / 2.5.6
Customify v2.5.6
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
← All changes | js/customizer.js +855 -725 1.2.42.5.6 View file →
@@ -1,1035 +1,1165 @@
1 -(function( $, exports ) {
2 - $( document ).ready( function() {
1 +(
2 + function ($, exports, wp) {
3 + var api = wp.customize
4 + var $window = $(window)
5 +
3 6 // when the customizer is ready prepare our fields events
4 - wp.customize.bind( 'ready', function() {
5 - var api = this,
6 - timeout = null;
7 + wp.customize.bind('ready', function () {
8 + var timeout = null
7 9
10 + // Create a stack of callbacks bound to parent settings to be able to unbind them
11 + // when altering the connected_fields attribute.
12 + if (typeof window.connectedFieldsCallbacks === 'undefined') {
13 + window.connectedFieldsCallbacks = {}
14 + }
15 +
8 16 // add ace editors
9 - $( '.customify_ace_editor' ).each( function( key, el ) {
10 - var id = $( this ).attr( 'id' ),
11 - css_editor = ace.edit( id );
17 + $('.customify_ace_editor').each(function (key, el) {
18 + const id = $(this).attr('id'),
19 + css_editor = ace.edit(id)
12 20
13 - var editor_type = $( this ).data( 'editor_type' );
21 + const editor_type = $(this).data('editor_type')
14 22 // init the ace editor
15 - css_editor.setTheme( "ace/theme/github" );
16 - css_editor.getSession().setMode( "ace/mode/" + editor_type );
23 + css_editor.setTheme('ace/theme/github')
24 + css_editor.getSession().setMode('ace/mode/' + editor_type)
17 25
18 26 // hide the textarea and enable the ace editor
19 - var textarea = $( '#' + id + '_textarea' ).hide();
20 - css_editor.getSession().setValue( textarea.val() );
27 + const textarea = $('#' + id + '_textarea').hide()
28 + css_editor.getSession().setValue(textarea.val())
21 29
22 30 // each time a change is triggered start a timeout of 1,5s and when is finished refresh the previewer
23 31 // if the user types faster than this delay then reset it
24 - css_editor.getSession().on( 'change', function( e ) {
25 - if ( timeout !== null ) {
26 - clearTimeout( timeout );
27 - timeout = null;
32 + css_editor.getSession().on('change', function (e) {
33 + if (timeout !== null) {
34 + clearTimeout(timeout)
35 + timeout = null
28 36 } else {
29 - timeout = setTimeout( function() {
37 + timeout = setTimeout(function () {
30 38 //var state = css_editor.session.getState();
31 - textarea.val( css_editor.getSession().getValue() );
32 - textarea.trigger( 'change' );
33 - }, 1500 );
39 + textarea.val(css_editor.getSession().getValue())
40 + textarea.trigger('change')
41 + }, 1500)
34 42 }
35 - } );
36 - } );
43 + })
44 + })
37 45
38 46 // simple select2 field
39 - $( '.customify_select2' ).select2();
47 + $('.customify_select2').select2()
40 48
41 - prepare_typography_field();
49 + setTimeout(function () {
50 + CustomifyFontSelectFields.init()
51 + }, 333)
42 52
53 + prepare_typography_field()
54 +
43 55 /**
44 56 * Make the customizer save on CMD/CTRL+S action
45 57 * This is awesome!!!
46 58 */
47 - $( window ).bind( 'keydown', function( event ) {
48 - if ( event.ctrlKey || event.metaKey ) {
49 - switch ( String.fromCharCode( event.which ).toLowerCase() ) {
59 + $(window).bind('keydown', function (event) {
60 + if (event.ctrlKey || event.metaKey) {
61 + switch (String.fromCharCode(event.which).toLowerCase()) {
50 62 case 's':
51 - event.preventDefault();
52 - api.previewer.save();
53 - break;
63 + event.preventDefault()
64 + api.previewer.save()
65 + break
54 66 }
55 67 }
56 - } );
68 + })
57 69
58 70 // for each range input add a value preview output
59 - $( 'input[type="range"]' ).each( function() {
60 - var $clone = $( this ).clone();
71 + $('.accordion-section-content[id*="' + customify_settings.options_name + '"], #sub-accordion-section-style_manager_section').each(function () {
61 72
62 - $clone
63 - .attr( 'type', 'number' )
64 - .attr( 'class', 'range-value' );
73 + // Initialize range fields logic
74 + customifyHandleRangeFields(this)
75 + })
65 76
66 - $( this ).after( $clone );
77 + $(document).on('change', '.customify_typography_font_subsets', function (ev) {
67 78
68 - $( this ).on( 'input', function() {
69 - $( this ).siblings( '.range-value' ).val( $( this ).val() );
70 - } );
71 - } );
79 + const $input = $(this).parents('.options').siblings('.customify_typography').children('.customify_typography_values');
80 + let current_val = $input.val()
72 81
73 - if ( $( 'button[data-action="reset_customify"]' ).length > 0 ) {
74 - // reset_button
75 - $( document ).on( 'click', '#customize-control-reset_customify button', function( ev ) {
76 - ev.preventDefault();
82 + current_val = JSON.parse(decodeURIComponent(current_val))
77 83
78 - var iAgree = confirm( 'Do you really want to reset to defaults all the fields? Watch out, this will reset all your Customify options and will save them!' );
84 + //maybe the selected option holds a JSON in its value
85 + current_val.selected_subsets = maybeJsonParse($(this).val())
79 86
80 - if ( !iAgree ) {
81 - return;
82 - }
87 + $input.val(encodeURIComponent(JSON.stringify(current_val)))
83 88
84 - $.each( api.settings.controls, function( key, ctrl ) {
85 - var id = key.replace( '_control', '' );
86 - var setting = customify_settings.settings[id];
89 + $input.trigger('change')
90 + })
87 91
88 - if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
92 + $(document).on('change', '.customify_typography_font_weight', function (ev) {
89 93
90 - var start_pos = id.indexOf( '[' ) + 1;
91 - var end_pos = id.indexOf( ']', start_pos );
94 + const $input = $(this).parents('.options').siblings('.customify_typography').children('.customify_typography_values');
95 + let current_val = $input.val();
92 96
93 - id = id.substring( start_pos, end_pos );
94 - api_set_setting_value( id, setting.default );
95 - }
96 - } );
97 + current_val = maybeJsonParse(current_val)
98 + // @todo currently the font weight selector works for one value only
99 + // maybe make this a multiselect
97 100
98 - api.previewer.save();
99 - } );
101 + //maybe the selected option holds a JSON in its value
102 + current_val.selected_variants = {0: maybeJsonParse($(this).val())}
100 103
101 - // add a reset button for each panel
102 - $( '.panel-meta' ).each( function( el, key ) {
103 - var container = $( this ).parents( '.control-panel' ),
104 - id = container.attr( 'id' ),
105 - panel_id = id.replace( 'accordion-panel-', '' );
104 + $input.val(encodeURIComponent(JSON.stringify(current_val)))
105 + $input.trigger('change')
106 + })
106 107
108 + $('body').on('customify:preset-change', function (e) {
109 + const data = $(e.target).data('options')
107 110
108 - $( this ).parent().append( '<button class="reset_panel button" data-panel="' + panel_id + '">Panel\'s defaults</button>' );
109 - } );
111 + if (!_.isUndefined(data)) {
112 + $.each(data, function (setting_id, value) {
113 + api_set_setting_value(setting_id, value)
114 + })
115 + }
116 + })
110 117
111 - // reset panel
112 - $( document ).on( 'click', '.reset_panel', function( e ) {
113 - e.preventDefault();
118 + $(document).on('change', 'select.js-customify-preset', function () {
119 + const $source = $(this)
120 + const $target = $source.children('[value="' + $source.val() + '"]')
121 + $target.trigger('customify:preset-change')
122 + })
114 123
115 - var panel_id = $( this ).data( 'panel' ),
116 - panel = api.panel( panel_id ),
117 - sections = panel.sections(),
118 - iAgree = confirm( "Do you really want to reset " + panel.params.title + "?" );
124 + $(document).on('click', '.js-customify-preset input', function () {
125 + $(this).trigger('customify:preset-change')
126 + })
119 127
120 - if ( !iAgree ) {
121 - return;
122 - }
123 - if ( sections.length > 0 ) {
124 - $.each( sections, function() {
125 - //var settings = this.settings();
126 - var controls = this.controls();
128 + customifyBackgroundJsControl.init()
127 129
128 - if ( controls.length > 0 ) {
129 - $.each( controls, function( key, ctrl ) {
130 - var id = ctrl.id.replace( '_control', '' ),
131 - setting = customify_settings.settings[id];
130 + // sometimes a php save may be needed
131 + if (getUrlVars('save_customizer_once')) {
132 + api.previewer.save()
133 + }
132 134
133 - if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
135 + setTimeout(function () {
136 + customifyFoldingFields()
137 + }, 1000);
134 138
135 - var start_pos = id.indexOf( '[' ) + 1,
136 - end_pos = id.indexOf( ']', start_pos );
139 + // Handle reset buttons
140 + handleResetButtons();
137 141
138 - id = id.substring( start_pos, end_pos );
139 - api_set_setting_value( id, setting.default );
140 - }
141 - } );
142 - }
143 - } );
144 - }
145 - } );
142 + // Handle the section tabs (ex: Layout | Fonts | Colors)
143 + handleSectionTabs();
144 + handleFontPopupToggle();
146 145
147 - //add reset section
148 - $( '.accordion-section-content' ).each( function( el, key ) {
149 - var section = $( this ).parent(),
150 - section_id = section.attr( 'id' );
146 + // Bind any connected fields, except those in the Style Manager.
147 + // Those are handled by the appropriate Style Manager component (Color Palettes, Font Palettes, etc ).
148 + bindConnectedFields()
149 + });
151 150
152 - if ( ( ( ! _.isUndefined( section_id ) ) ? section_id.indexOf( customify_settings.options_name ) : -1 ) === -1 ) {
153 - return;
154 - }
151 + function handleResetButtons() {
152 + var showResetButtons = $( 'button[data-action="reset_customify"]' ).length > 0;
155 153
156 - if ( ! _.isUndefined( section_id ) && section_id.indexOf( 'accordion-section-' ) > -1 ) {
157 - var id = section_id.replace( 'accordion-section-', '' );
158 - $( this ).prepend( '<button class="reset_section button" data-section="' + id + '">Section\'s defaults</button>' );
159 - }
160 - } );
154 + if ( showResetButtons ) {
155 + createResetPanelButtons();
156 + createResetSectionButtons();
161 157
162 - // reset section event
163 - $( document ).on( 'click', '.reset_section', function( e ) {
164 - e.preventDefault();
158 + $( document ).on( 'click', '.js-reset-panel', onResetPanel );
159 + $( document ).on( 'click', '.js-reset-section', onResetSection );
160 + $( document ).on( 'click', '#customize-control-reset_customify button', onReset );
161 + }
162 + }
165 163
166 - var section_id = $( this ).data( 'section' ),
167 - section = api.section( section_id ),
168 - controls = section.controls();
164 + function handleFontPopupToggle() {
165 + var $allCheckboxes = $( '.js-font-option-toggle' );
166 + // Close a font field when clicking on another field
167 + $allCheckboxes.on( 'click', function() {
168 + var $checkbox = $( this );
169 + if ( $checkbox.prop( 'checked' ) === true ) {
170 + $allCheckboxes.not( $checkbox ).prop( 'checked', false );
171 + }
172 + } )
173 + }
169 174
170 - var iAgree = confirm( "Do you really want to reset " + section.params.title + "?" );
175 + function createResetPanelButtons() {
171 176
172 - if ( !iAgree ) {
173 - return;
174 - }
177 + $( '.panel-meta' ).each( function( i, obj ) {
178 + var $this = $( obj )
179 + var container = $this.parents('.control-panel');
180 + var id = container.attr('id');
175 181
176 - if ( controls.length > 0 ) {
177 - $.each( controls, function( key, ctrl ) {
178 - var id = ctrl.id.replace( '_control', '' ),
179 - setting = customify_settings.settings[id];
182 + if ( typeof id !== 'undefined' ) {
183 + id = id.replace( 'sub-accordion-panel-', '' );
184 + id = id.replace( 'accordion-panel-', '' );
185 + var $buttonWrapper = $( '<li class="customize-control customize-control-reset"></li>' );
186 + var $button = $( '<button class="button js-reset-panel" data-panel="' + id + '"></button>' );
180 187
181 - if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
188 + $button.text( "Panel's defaults" ).appendTo( $buttonWrapper );
189 + $this.parent().append( $buttonWrapper );
190 + }
191 + })
192 + }
182 193
183 - var start_pos = id.indexOf( '[' ) + 1,
184 - end_pos = id.indexOf( ']', start_pos );
194 + function createResetSectionButtons() {
195 + $( '.accordion-section-content' ).each( function( el, key ) {
196 + var $this = $( this );
197 + var section_id = $this.attr( 'id' );
185 198
186 - id = id.substring( start_pos, end_pos );
187 - api_set_setting_value( id, setting.default );
188 - }
189 - } );
190 - }
191 - } );
192 - }
199 + if ( _.isUndefined( section_id ) || section_id.indexOf( customify_settings.options_name ) === - 1 ) {
200 + return;
201 + }
193 202
194 - $( document ).on( 'change', '.customize-control input.range-value', function() {
195 - var range = $( this ).siblings( 'input[type="range"]' );
196 - range.val( $( this ).val() );
197 - } );
203 + var id = section_id.replace( 'sub-accordion-section-', '' );
204 + var $button = $( '<button class="button js-reset-section" data-section="' + id + '"></button>' );
205 + var $buttonWrapper = $( '<li class="customize-control customize-control-reset"></li>' );
198 206
199 - $( document ).on( 'change', '.customify_typography_font_subsets', function( ev ) {
207 + $button.text( 'Reset All Options for This Section' );
208 + $buttonWrapper.append( $button );
200 209
201 - var $input = $( this ).parents( '.options' ).siblings( '.customify_typography' ).children( '.customify_typography_values' ),
202 - current_val = $input.val();
210 + $this.append( $buttonWrapper );
211 + } );
212 + }
203 213
204 - current_val = JSON.parse( decodeURIComponent( current_val ) );
214 + function onReset(ev) {
215 + ev.preventDefault()
205 216
206 - //maybe the selected option holds a JSON in its value
207 - current_val.selected_subsets = maybeJsonParse( $( this ).val() );
217 + var iAgree = confirm( 'Do you really want to reset to defaults all the fields? Watch out, this will reset all your Customify options and will save them!' )
208 218
209 - $input.val( encodeURIComponent( JSON.stringify( current_val ) ) );
219 + if ( ! iAgree ) {
220 + return
221 + }
210 222
211 - $input.trigger( 'change' );
212 - } );
223 + $.each( api.settings.controls, function( key, ctrl ) {
224 + const setting_id = key.replace( '_control', '' )
225 + const setting = customify_settings.settings[setting_id]
213 226
214 - $( document ).on( 'change', '.customify_typography_font_weight', function( ev ) {
227 + if ( !_.isUndefined( setting ) && !_.isUndefined( setting.default ) ) {
228 + api_set_setting_value( setting_id, setting.default )
229 + }
230 + } );
215 231
216 - var $input = $( this ).parents( '.options' ).siblings( '.customify_typography' ).children( '.customify_typography_values' ),
217 - current_val = $input.val();
232 + api.previewer.save();
233 + }
218 234
219 - current_val = maybeJsonParse( current_val );
220 - // @todo currently the font weight selector works for one value only
221 - // maybe make this a multiselect
235 + function onResetPanel(e) {
236 + e.preventDefault()
222 237
223 - //maybe the selected option holds a JSON in its value
224 - current_val.selected_variants = {0: maybeJsonParse( $( this ).val() ) };
238 + const panel_id = $(this).data('panel'),
239 + panel = api.panel(panel_id),
240 + sections = panel.sections(),
241 + iAgree = confirm('Do you really want to reset ' + panel.params.title + '?')
225 242
226 - $input.val( encodeURIComponent( JSON.stringify( current_val ) ) );
227 - $input.trigger( 'change' );
228 - } );
243 + if (!iAgree) {
244 + return
245 + }
246 + if (sections.length > 0) {
247 + $.each(sections, function () {
248 + //var settings = this.settings();
249 + const controls = this.controls()
229 250
230 - // presets
231 - $( document ).on( 'change', '.customify_preset.select', function() {
232 - var api = wp.customize,
233 - this_option = $( this ).children( '[value="' + $( this ).val() + '"]' ),
234 - data = $( this_option ).data( 'options' );
251 + if (controls.length > 0) {
252 + $.each(controls, function (key, ctrl) {
253 + const setting_id = ctrl.id.replace('_control', ''),
254 + setting = customify_settings.settings[setting_id]
235 255
236 - if ( ! _.isUndefined( data ) ) {
237 - $.each( data, function( id, value ) {
238 - api_set_setting_value( id, value );
239 - } );
256 + if (!_.isUndefined(setting) && !_.isUndefined(setting.default)) {
257 + api_set_setting_value(setting_id, setting.default)
258 + }
259 + })
260 + }
261 + })
262 + }
263 + }
264 +
265 + function onResetSection(e) {
266 + e.preventDefault()
267 +
268 + const section_id = $(this).data('section'),
269 + section = api.section(section_id),
270 + controls = section.controls()
271 +
272 + const iAgree = confirm('Do you really want to reset ' + section.params.title + '?')
273 +
274 + if (!iAgree) {
275 + return
276 + }
277 +
278 + if (controls.length > 0) {
279 + $.each(controls, function (key, ctrl) {
280 + const setting_id = ctrl.id.replace('_control', ''),
281 + setting = customify_settings.settings[setting_id]
282 +
283 + if (!_.isUndefined(setting) && !_.isUndefined(setting.default)) {
284 + api_set_setting_value(setting_id, setting.default)
285 + }
286 + })
287 + }
288 + }
289 +
290 + function handleSectionTabs() {
291 + const $navs = $( '.js-section-navigation' );
292 +
293 + $navs.each( function() {
294 + var $nav = $( this )
295 + var $title = $nav.parents( '.accordion-section-content' ).find( '.customize-section-title' );
296 + var $parent = $nav.closest( '.customize-control' );
297 +
298 + $nav.appendTo( $title );
299 + $title.parent().addClass( 'has-nav' );
300 + $parent.addClass( 'screen-reader-text' );
301 + } );
302 +
303 + $( '.js-section-navigation a' ).on( 'click', function( e ) {
304 + e.preventDefault();
305 +
306 + var $this = $( this );
307 + var $sidebar = $this.parents( '.wp-full-overlay-sidebar-content' );
308 + var $parent = $this.parents( '.accordion-section-content' );
309 + var href = $this.attr('href' );
310 +
311 + if ( href != '#' ) {
312 + var actionsHeight = $( '#customize-header-actions' ).outerHeight();
313 + var titleHeight = $parent.find( '.customize-section-title' ).outerHeight();
314 + var $target = $( href );
315 + var offset = $target.position().top;
316 +
317 + $sidebar.animate( { scrollTop: offset - titleHeight - actionsHeight }, 500 );
318 + }
319 + } );
320 + }
321 +
322 + const getConnectedFieldsCallback = function (parent_setting_data, parent_setting_id) {
323 + return function (new_value, old_value) {
324 + _.each(parent_setting_data.connected_fields, function (connected_field_data) {
325 + if (_.isUndefined(connected_field_data) || _.isUndefined(connected_field_data.setting_id) || !_.isString(connected_field_data.setting_id)) {
326 + return
327 + }
328 + const setting = wp.customize(connected_field_data.setting_id)
329 + if (_.isUndefined(setting)) {
330 + return
331 + }
332 + setting.set(new_value)
333 + })
334 + }
335 + }
336 +
337 + const bindConnectedFields = function () {
338 + _.each(wp.customize.settings.settings, function (parent_setting_data, parent_setting_id) {
339 + // We don't want to handle the binding of the Style Manager settings
340 + if (typeof ColorPalettes !== 'undefined'
341 + && typeof ColorPalettes.masterSettingIds !== 'undefined'
342 + && _.contains(ColorPalettes.masterSettingIds, parent_setting_id)) {
343 + return
240 344 }
345 + if (typeof FontPalettes !== 'undefined'
346 + && typeof FontPalettes.masterSettingIds !== 'undefined'
347 + && _.contains(FontPalettes.masterSettingIds, parent_setting_id)) {
348 + return
349 + }
241 350
242 - api.previewer.refresh();
243 - } );
351 + let parent_setting = wp.customize(parent_setting_id)
352 + if (typeof parent_setting_data.connected_fields !== 'undefined') {
353 + connectedFieldsCallbacks[parent_setting_id] = getConnectedFieldsCallback(parent_setting_data, parent_setting_id)
354 + parent_setting.bind(connectedFieldsCallbacks[parent_setting_id])
355 + }
356 + })
357 + }
244 358
245 - $( document ).on( 'click', '.customify_preset.radio input, .customify_preset.radio_buttons input, .awesome_presets input', function() {
246 - var api = wp.customize;
247 - var this_option = this;//$(this).children('[value="' + $(this).val() + '"]');
248 - var data = $( this_option ).data( 'options' );
359 + const unbindConnectedFields = function () {
360 + _.each(wp.customize.settings.settings, function (parent_setting_data, parent_setting_id) {
361 + // We don't want to handle the binding of the Style Manager settings
362 + if (typeof ColorPalettes !== 'undefined'
363 + && typeof ColorPalettes.masterSettingIds !== 'undefined'
364 + && _.contains(ColorPalettes.masterSettingIds, parent_setting_id)) {
365 + return
366 + }
367 + if (typeof FontPalettes !== 'undefined'
368 + && typeof FontPalettes.masterSettingIds !== 'undefined'
369 + && _.contains(FontPalettes.masterSettingIds, parent_setting_id)) {
370 + return
371 + }
249 372
250 - if ( ! _.isUndefined( data ) ) {
251 - $.each( data, function( id, value ) {
252 - api_set_setting_value( id, value );
253 - } );
373 + let parent_setting = wp.customize(parent_setting_id)
374 + if (typeof parent_setting_data.connected_fields !== 'undefined' && typeof connectedFieldsCallbacks[parent_setting_id] !== 'undefined') {
375 + parent_setting.unbind(connectedFieldsCallbacks[parent_setting_id])
254 376 }
377 + delete connectedFieldsCallbacks[parent_setting_id]
378 + })
379 + }
255 380
256 - api.previewer.refresh();
257 - } );
381 + const customifyHandleRangeFields = function (el) {
258 382
259 - // bind our event on click
260 - $( document ).on( 'click', '.customify_import_demo_data_button', function( event ) {
261 - //if ( $( this ).hasClass( '.wpGrade_button_inactive' ) ) {
262 - // return false;
263 - //} else {
264 - // $( this ).addClass( '.wpGrade_button_inactive' );
265 - // $( this ).attr( 'disabled', 'disabled' );
266 - //}
267 - //var confirmImport = confirm( listable_demodata_params.l10n.import_confirm );
268 - //if ( confirmImport == false ) return false;
383 + // For each range input add a number field (for preview mainly - but it can also be used for input)
384 + $( el ).find( 'input[type="range"]' ).each( function() {
385 + var $range = $( this ),
386 + $number = $range.siblings( '.range-value' );
269 387
270 - //@todo start an animation here
271 - var key = $( this ).data( 'key' );
388 + if ( ! $number.length ) {
389 + $number = $range.clone();
272 390
273 - var import_queue = new Queue( api );
391 + $number
392 + .attr( 'type', 'number' )
393 + .attr( 'class', 'range-value' )
394 + .removeAttr( 'data-field' )
395 + .insertAfter( $range );
396 + }
274 397
275 - /// calculate the number of steps
276 - var steps = [];
398 + function hasValidValue( $input ) {
399 + var min = $input.attr( 'min' );
400 + var max = $input.attr( 'max' );
401 + var value = $input.val();
277 402
278 - if ( ! _.isUndefined( customify_settings.settings[key].imports ) ) {
403 + if ( typeof min !== "undefined" && parseFloat( min ) > parseFloat( value ) ) {
404 + return false;
405 + }
279 406
280 - $.each( customify_settings.settings[key].imports, function( i, import_setts, k ) {
281 - if ( _.isUndefined( import_setts.steps ) ) {
282 - steps.push( {id: i, type: import_setts.type} );
283 - } else {
284 - var count = import_setts.steps;
407 + if ( typeof max !== "undefined" && parseFloat( max ) < value ) {
408 + return false;
409 + }
285 410
286 - while ( count >= 1 ) {
287 - steps.push( {id: i, type: import_setts.type, count: count} );
288 - count = count - 1;
289 - }
290 - }
291 - } );
292 - }
411 + return true;
412 + }
293 413
294 - import_queue.add_steps( 'import_demo_data_action_id', steps );
295 - return false;
296 - } );
414 + $range.on( 'input', function() {
415 + $number.val( $range.val() );
416 + } );
297 417
298 - customifyBackgroundJsControl.init();
418 + $number.on( 'blur', function() {
419 + if ( ! hasValidValue( $number ) ) {
420 + $number.val( $range.val() );
421 + shake( $number );
422 + } else {
423 + $range.val( $number.val() );
424 + }
425 + } );
299 426
300 - // sometimes there may be needed a php save
301 - if ( getUrlVars( 'save_customizer_once' ) ) {
302 - api.previewer.save();
303 - }
427 + function shake( $field ) {
428 + $field.addClass( 'input-shake input-error' );
429 + $field.one( 'animationend', function() {
430 + $field.removeClass( 'input-shake input-error' );
431 + } );
432 + }
433 + })
434 + }
304 435
305 - setTimeout(function () {
306 - customifyFoldingFields();
307 - }, 1000);
308 - } );
309 -
310 436 /**
311 437 * This function will search for all the interdependend fields and make a bound between them.
312 438 * So whenever a target is changed, it will take actions to the dependent fields.
439 + * @TODO this is still written in a barbaric way, refactor when needed
313 440 */
314 - var customifyFoldingFields = function() {
441 + const customifyFoldingFields = function () {
315 442
316 - if ( _.isUndefined( customify_settings ) || _.isUndefined( customify_settings.settings ) ) {
317 - return ; // bail
443 + if (_.isUndefined(customify_settings) || _.isUndefined(customify_settings.settings)) {
444 + return // bail
318 445 }
319 446
320 447 /**
321 - * Let's iterate through all the customify settings and gather all the fields that have a "show_on"
448 + * Let's iterate through all the customify settings and gather all the fields that have a "show_if"
322 449 * property set.
323 450 *
324 451 * At the end `targets` will hold a list of [ target : [field, field,...], ... ]
325 452 * so when a target is changed we will change all the fields.
326 453 */
327 - var targets = {};
454 + var targets = {}
328 455
329 - $.fn.reactor.defaults.compliant = function() {
330 - $(this).slideDown();
456 + $.fn.reactor.defaults.compliant = function () {
457 + $(this).slideDown()
331 458 // $(this).animate({opacity: 1});
332 - $(this).find(':disabled').attr({disabled: false});
333 - };
459 + $(this).find(':disabled').attr({disabled: false})
460 + }
334 461
335 - $.fn.reactor.defaults.uncompliant = function() {
336 - $(this).slideUp();
462 + $.fn.reactor.defaults.uncompliant = function () {
463 + $(this).slideUp()
337 464 // $(this).animate({opacity: 0.25});
338 - $(this).find(':enabled').attr({disabled: true});
339 - };
465 + $(this).find(':enabled').attr({disabled: true})
466 + }
340 467
341 - var IS = $.extend({}, $.fn.reactor.helpers);
468 + let IS = $.extend({}, $.fn.reactor.helpers)
342 469
343 - var process_a_target = function( parent_id, field ) {
470 + let bind_folding_events = function (parent_id, field, relation) {
344 471
345 - if ( _.isUndefined( field[0] ) ) {
346 - return ; // no id, no fun
472 + let key = null
473 +
474 + if (_.isString(field)) {
475 + key = field
476 + } else if (!_.isUndefined(field.id)) {
477 + key = field.id
478 + } else if (isString(field[0])) {
479 + key = field[0]
480 + } else {
481 + return // no key, no fun
347 482 }
348 483
349 - var key = field[0],
350 - value = 1, // by default we use 1 the most used value for checboxes or inputs
484 + let value = 1, // by default we use 1 the most used value for checkboxes or inputs
351 485 compare = '==', // ... ye
352 - action = "show"; // can only be `show` or `hide`
486 + action = 'show',
487 + between = [0, 1] // can only be `show` or `hide`
353 488
354 - var target_key = customify_settings.options_name + '[' + key + ']';
355 - var target_type = customify_settings.settings[ target_key ].type;
489 + const target_key = customify_settings.options_name + '[' + key + ']'
490 + const target_type = customify_settings.settings[target_key].type
356 491
492 + // we support the usual syntax like a config array like `array( 'id' => $id, 'value' => $value, 'compare' => $compare )`
493 + // but we also support a non-associative array like `array( $id, $value, $compare )`
494 + if (!_.isUndefined(field.value)) {
495 + value = field.value
496 + } else if (!_.isUndefined(field[1]) && !_.isString(field[1])) {
497 + value = field[1]
498 + }
357 499
358 - if ( ! _.isUndefined( field[1] ) ) {
359 - value = field[1];
500 + if (!_.isUndefined(field.compare)) {
501 + compare = field.compare
502 + } else if (!_.isUndefined(field[2])) {
503 + compare = field[2]
360 504 }
361 505
362 - if ( ! _.isUndefined( field[2] ) ) {
363 - compare = field[2];
506 + if (!_.isUndefined(field.action)) {
507 + action = field.action
508 + } else if (!_.isUndefined(field[3])) {
509 + action = field[3]
364 510 }
365 511
366 - if ( ! _.isUndefined( field[3] ) ) {
367 - action = field[3];
512 + // a field can also overwrite the parent relation
513 + if (!_.isUndefined(field.relation)) {
514 + action = field.relation
515 + } else if (!_.isUndefined(field[4])) {
516 + action = field[4]
368 517 }
369 518
519 + if (!_.isUndefined(field.between)) {
520 + between = field.between
521 + }
522 +
370 523 /**
371 524 * Now for each target we have, we will bind a change event to hide or show the dependent fields
372 525 */
373 - var target_selector = '[data-customize-setting-link="' + customify_settings.options_name + '[' + key + ']"]';
526 + const target_selector = '[data-customize-setting-link="' + customify_settings.options_name + '[' + key + ']"]'
374 527
375 - if ( target_type == 'checkbox' ) {
376 - $(parent_id).reactIf( target_selector, function () {
377 - return $( this ).is(':checked') == value;
378 - } );
379 - } else if ( target_type == 'radio' || target_type == 'radio_image' ) {
380 - $(parent_id)
381 - .reactIf( target_selector, function () {
382 - return $( target_selector + ':checked').val() == value;
383 - } );
384 - } else {
385 - $(parent_id)
386 - .reactIf( target_selector, function () {
387 - return $(target_selector).val() == value;
388 - } );
528 + switch (target_type) {
529 + case 'checkbox':
530 + $(parent_id).reactIf(target_selector, function () {
531 + return $(this).is(':checked') == value
532 + })
533 + break
534 +
535 + case 'radio':
536 + case 'sm_radio':
537 + case 'sm_switch':
538 + case 'radio_image':
539 + case 'radio_html':
540 +
541 + // in case of an array of values we use the ( val in array) condition
542 + if (_.isObject(value)) {
543 + $(parent_id).reactIf(target_selector, function () {
544 + return (
545 + value.indexOf($(target_selector + ':checked').val()) !== -1
546 + )
547 + })
548 + } else { // in any other case we use a simple == comparison
549 + $(parent_id).reactIf(target_selector, function () {
550 + return $(target_selector + ':checked').val() == value
551 + })
552 + }
553 + break
554 +
555 + case 'range':
556 + const x = IS.Between(between[0], between[1])
557 +
558 + $(parent_id).reactIf(target_selector, x)
559 + break
560 +
561 + default:
562 + // in case of an array of values we use the ( val in array) condition
563 + if (_.isObject(value)) {
564 + $(parent_id).reactIf(target_selector, function () {
565 + return (
566 + value.indexOf($(target_selector).val()) !== -1
567 + )
568 + })
569 + } else { // in any other case we use a simple == comparison
570 + $(parent_id).reactIf(target_selector, function () {
571 + return $(target_selector).val() == value
572 + })
573 + }
574 + break
389 575 }
390 576
391 - $(target_selector).trigger('change');
392 - $('.reactor').trigger('change.reactor'); // triggers all events on load
393 - };
577 + $(target_selector).trigger('change')
578 + $('.reactor').trigger('change.reactor') // triggers all events on load
579 + }
394 580
395 - $.each( customify_settings.settings, function ( id, field ) {
396 -
581 + $.each(customify_settings.settings, function (id, field) {
397 582 /**
398 583 * Here we have the id of the fields. but we know for sure that we just need his parent selector
399 584 * So we just create it
400 585 */
401 - var parent_id = id.replace( '[', '-' );
402 - parent_id = parent_id.replace( ']', '' );
403 - parent_id = '#customize-control-' + parent_id + '_control';
586 + let parent_id = id.replace('[', '-')
587 + parent_id = parent_id.replace(']', '')
588 + parent_id = '#customize-control-' + parent_id + '_control'
404 589
590 + // get only the fields that have a 'show_if' property
591 + if (field.hasOwnProperty('show_if')) {
592 + let relation = 'AND'
405 593
406 - // get only the fields that have a 'show_on' property
407 - if ( field.hasOwnProperty( 'show_on' ) && field.show_on.length > 0 ) {
594 + if (!_.isUndefined(field.show_if.relation)) {
595 + relation = field.show_if.relation
596 + // remove the relation property, we need the config to be array based only
597 + delete field.show_if.relation
598 + }
408 599
409 600 /**
410 - * The 'show_on' can be a simple array with one target like: [ id, value, comparison, action ]
601 + * The 'show_if' can be a simple array with one target like: [ id, value, comparison, action ]
411 602 * Or it could be an array of multiple targets and we need to process both cases
412 603 */
413 - if ( _.isString( field.show_on[0] ) ) {
414 - process_a_target( parent_id, field.show_on );
415 - } else if ( _.isObject( field.show_on[0] ) ) {
416 - $.each( field.show_on, function (i, j) {
417 - process_a_target( parent_id, j );
418 - });
604 +
605 + if (!_.isUndefined(field.show_if.id)) {
606 + bind_folding_events(parent_id, field.show_if, relation)
607 + } else if (_.isObject(field.show_if)) {
608 + $.each(field.show_if, function (i, j) {
609 + bind_folding_events(parent_id, j, relation)
610 + })
419 611 }
420 612 }
421 - });
422 - };
613 + })
614 + }
423 615
424 - var get_typography_font_family = function( $el ) {
616 + const get_typography_font_family = function ($el) {
425 617
426 - var font_family_value = $el.val();
618 + let font_family_value = $el.val()
427 619 // first time this will not be a json so catch that error
428 620 try {
429 - font_family_value = JSON.parse( font_family_value );
430 - } catch ( e ) {
431 - return {font_family: font_family_value};
621 + font_family_value = JSON.parse(font_family_value)
622 + } catch (e) {
623 + return {font_family: font_family_value}
432 624 }
433 625
434 - if ( ! _.isUndefined( font_family_value.font_family ) ) {
435 - return font_family_value.font_family;
626 + if (!_.isUndefined(font_family_value.font_family)) {
627 + return font_family_value.font_family
436 628 }
437 629
438 - return false;
439 - };
630 + return false
631 + }
440 632
441 633 // get each typography field and bind events
442 - var prepare_typography_field = function() {
634 + // @todo Are we still using the typography field since we have the font field?
635 + // Yes we do, in older themes.
636 + const prepare_typography_field = function () {
443 637
444 - var $typos = $( '.customify_typography_font_family' );
638 + const $typos = $('.customify_typography_font_family')
445 639
446 - $typos.each( function() {
640 + $typos.each(function () {
447 641 var font_family_select = this,
448 - $input = $( font_family_select ).siblings( '.customify_typography_values' );
642 + $input = $(font_family_select).siblings('.customify_typography_values')
449 643 // on change
450 - $( font_family_select ).on( 'change', function() {
451 - update_siblings_selects( font_family_select );
452 - $input.trigger( 'change' );
453 - } );
454 - update_siblings_selects( font_family_select );
455 - } );
456 - };
644 + $(font_family_select).on('change', function () {
645 + update_siblings_selects(font_family_select)
646 + $input.trigger('change')
647 + })
648 + update_siblings_selects(font_family_select)
649 + })
650 + }
457 651
458 - var api_set_setting_value = function( id, value ) {
652 + const api_set_setting_value = function (setting_id, value) {
653 + let setting = api(setting_id),
654 + field = $('[data-customize-setting-link="' + setting_id + '"]'),
655 + field_class = $(field).parent().attr('class')
459 656
460 - var api = wp.customize,
461 - setting_id = customify_settings.options_name + '[' + id + ']',
462 - setting = api( setting_id ),
463 - field = $( '[data-customize-setting-link="' + setting_id + '"]' ),
464 - field_class = $( field ).parent().attr( 'class' );
657 + // Legacy field type
658 + if (!_.isUndefined(field_class) && field_class === 'customify_typography') {
465 659
466 - if ( ! _.isUndefined( field_class ) && field_class === 'customify_typography' ) {
660 + let family_select = field.siblings('select')
467 661
468 - var family_select = field.siblings( 'select' );
662 + if (_.isString(value)) {
663 + let this_option = family_select.find('option[value="' + value + '"]')
664 + $(this_option[0]).attr('selected', 'selected')
665 + update_siblings_selects(family_select)
666 + } else if (_.isObject(value)) {
667 + let this_family_option = family_select.find('option[value="' + value['font_family'] + '"]')
469 668
470 - if ( _.isString( value ) ) {
471 - var this_option = family_select.find( 'option[value="' + value + '"]' );
472 - $( this_option[0] ).attr( 'selected', 'selected' );
473 - update_siblings_selects( family_select );
474 - } else if ( _.isObject( value ) ) {
475 - var this_family_option = family_select.find( 'option[value="' + value['font_family'] + '"]' );
476 - $( this_family_option[0] ).attr( 'selected', 'selected' );
669 + $(this_family_option[0]).attr('selected', 'selected')
477 670
478 - update_siblings_selects( this_family_option );
671 + update_siblings_selects(this_family_option)
479 672
480 - setTimeout( function() {
481 - var weight_select = field.parent().siblings( '.options' ).find( '.customify_typography_font_weight' );
673 + setTimeout(function () {
674 + let weight_select = field.parent().siblings('.options').find('.customify_typography_font_weight'),
675 + this_weight_option = weight_select.find('option[value="' + value['selected_variants'] + '"]')
482 676
483 - var this_weight_option = weight_select.find( 'option[value="' + value['selected_variants'] + '"]' );
677 + $(this_weight_option[0]).attr('selected', 'selected')
484 678
485 - $( this_weight_option[0] ).attr( 'selected', 'selected' );
679 + update_siblings_selects(this_family_option)
486 680
487 - update_siblings_selects( this_family_option );
681 + weight_select.trigger('change')
682 + }, 300)
683 + }
488 684
489 - weight_select.trigger( 'change' );
490 - }, 300 );
685 + family_select.trigger('change')
686 +
687 + } else if (!_.isUndefined(field_class) && field_class === 'font-options__wrapper') {
688 +
689 + // if the value is a simple string it must be the font family
690 + if (_.isString(value)) {
691 + let option = field.parent().find('option[value="' + value + '"]')
692 +
693 + option.attr('selected', 'selected')
694 + // option.parents('select').trigger('change');
695 + } else if (_.isObject(value)) {
696 + // Find the options list wrapper
697 + let optionsList = field.parent().children('.font-options__options-list')
698 +
699 + if (optionsList.length) {
700 + // We will process each font property and update it
701 + _.each(value, function (val, key) {
702 + // We need to map the keys to the data attributes we are using - I know :(
703 + let mappedKey = key
704 + switch (key) {
705 + case 'font-family':
706 + mappedKey = 'font_family'
707 + break
708 + case 'font-size':
709 + mappedKey = 'font_size'
710 + break
711 + case 'font-weight':
712 + mappedKey = 'selected_variants'
713 + break
714 + case 'letter-spacing':
715 + mappedKey = 'letter_spacing'
716 + break
717 + case 'text-transform':
718 + mappedKey = 'text_transform'
719 + break
720 + default:
721 + break
722 + }
723 + let subField = optionsList.find('[data-field="' + mappedKey + '"]')
724 + if (subField.length) {
725 + subField.val(val)
726 + subField.trigger('change')
727 + }
728 + })
729 + }
491 730 }
492 731
493 - family_select.trigger( 'change' );
494 -
495 732 } else {
496 - setting.set( value );
733 + setting.set(value)
497 734 }
498 - };
735 + }
499 736
500 - var update_siblings_selects = function( font_select ) {
737 + const update_siblings_selects = function (font_select) {
738 + let selected_font = $(font_select).val(),
739 + $input = $(font_select).siblings('.customify_typography_values'),
740 + current_val = $input.attr('value')
501 741
502 - this.bound_once = false;
503 - var selected_font = $( font_select ).val(),
504 - $input = $( font_select ).siblings( '.customify_typography_values' ),
505 - current_val = $input.attr( 'value' );
506 -
507 - if ( current_val === '[object Object]' ) {
508 - current_val = $input.data( 'default' );
509 - } else if ( _.isString( current_val ) && !isJsonString( current_val ) && current_val.substr(0,1) == '[' ) {
742 + if (current_val === '[object Object]') {
743 + current_val = $input.data('default')
744 + } else if (_.isString(current_val) && !isJsonString(current_val)) {
510 745 // a rare case when the value isn't a json but is a representative string like [family,weight]
511 - current_val = current_val.split( ',' );
512 - var new_current_value = {};
513 - if ( ! _.isUndefined( current_val[0] ) ) {
514 - new_current_value['font_family'] = current_val[0];
746 + current_val = current_val.split(',')
747 + let new_current_value = {}
748 + if (!_.isUndefined(current_val[0])) {
749 + new_current_value['font_family'] = current_val[0]
515 750 }
516 751
517 - if ( ! _.isUndefined( current_val[1] ) ) {
518 - new_current_value['selected_variants'] = current_val[1];
752 + if (!_.isUndefined(current_val[1])) {
753 + new_current_value['selected_variants'] = current_val[1]
519 754 }
520 755
521 - current_val = JSON.stringify( new_current_value );
756 + current_val = JSON.stringify(new_current_value)
522 757 }
523 758
524 - var $font_weight = $( font_select ).parent().siblings( 'ul.options' ).find( '.customify_typography_font_weight' ),
525 - $font_subsets = $( font_select ).parent().siblings( 'ul.options' ).find( '.customify_typography_font_subsets' );
759 + let $font_weight = $(font_select).parent().siblings('ul.options').find('.customify_typography_font_weight'),
760 + $font_subsets = $(font_select).parent().siblings('ul.options').find('.customify_typography_font_subsets')
526 761
527 762 try {
528 - current_val = JSON.parse( decodeURIComponent( current_val ) );
529 - } catch ( e ) {
763 + current_val = JSON.parse(decodeURIComponent(current_val))
764 + } catch (e) {
530 765
531 766 // in case of an error, force the rebuild of the json
532 - if ( _.isUndefined( $( font_select ).data( 'bound_once' ) ) ) {
767 + if (_.isUndefined($(font_select).data('bound_once'))) {
533 768
534 - $( font_select ).data( 'bound_once', true );
535 - //var api = wp.customize;
536 - //api.previewer.refresh();
769 + $(font_select).data('bound_once', true)
537 770
538 - $( font_select ).change();
539 - $font_weight.change();
540 - $font_subsets.change();
771 + $(font_select).change()
772 + $font_weight.change()
773 + $font_subsets.change()
541 774 }
542 775 }
543 776
544 777 // first try to get the font from sure sources, not from the recommended list.
545 - var option_data = $( font_select ).find( ':not(optgroup[label=Recommended]) option[value="' + selected_font + '"]' );
778 + let option_data = $(font_select).find(':not(optgroup[label=Recommended]) option[value="' + selected_font + '"]')
546 779 // however, if there isn't an option found, get what you can
547 - if ( option_data.length < 1 ) {
548 - option_data = $( font_select ).find( 'option[value="' + selected_font + '"]' );
780 + if (option_data.length < 1) {
781 + option_data = $(font_select).find('option[value="' + selected_font + '"]')
549 782 }
550 783
551 - if ( option_data.length > 0 ) {
784 + if (option_data.length > 0) {
552 785
553 - var font_type = option_data.data( 'type' ),
786 + let font_type = option_data.data('type'),
554 787 value_to_add = {'type': font_type, 'font_family': selected_font},
555 788 variants = null,
556 - subsets = null;
789 + subsets = null
557 790
558 - if ( font_type == 'std' ) {
559 - variants = { 0: '100', 1: '200', 3: '300', 4: '400', 5: '500', 6: '600', 7: '700', 8: '800', 9: '900' };
560 - if ( ! _.isUndefined( $( option_data[0] ).data( 'variants' ) ) ) {
791 + if (font_type == 'std') {
792 + variants = {
793 + 0: '100',
794 + 1: '200',
795 + 3: '300',
796 + 4: '400',
797 + 5: '500',
798 + 6: '600',
799 + 7: '700',
800 + 8: '800',
801 + 9: '900'
802 + }
803 + if (!_.isUndefined($(option_data[0]).data('variants'))) {
561 804 //maybe the variants are a JSON
562 - variants = maybeJsonParse( $( option_data[0] ).data( 'variants' ) );
805 + variants = maybeJsonParse($(option_data[0]).data('variants'))
563 806 }
564 807 } else {
565 808 //maybe the variants are a JSON
566 - variants = maybeJsonParse( $( option_data[0] ).data( 'variants' ) );
809 + variants = maybeJsonParse($(option_data[0]).data('variants'))
567 810
568 811 //maybe the subsets are a JSON
569 - subsets = maybeJsonParse( $( option_data[0] ).data( 'subsets' ) );
812 + subsets = maybeJsonParse($(option_data[0]).data('subsets'))
570 813 }
571 814
572 815 // make the variants selector
573 - if ( ! _.isUndefined( variants ) && ! _.isNull( variants ) && ! _.isEmpty( variants ) ) {
816 + if (!_.isUndefined(variants) && !_.isNull(variants) && !_.isEmpty(variants)) {
574 817
575 - value_to_add['variants'] = variants;
818 + value_to_add['variants'] = variants
576 819 // when a font is selected force the first weight to load
577 - value_to_add['selected_variants'] = {0: variants[0]};
820 + value_to_add['selected_variants'] = {0: variants[0]}
578 821
579 - var variants_options = '',
580 - count_weights = 0;
822 + let variants_options = '',
823 + count_weights = 0
581 824
582 - if ( _.isArray( variants ) || _.isObject( variants ) ) {
825 + if (_.isArray(variants) || _.isObject(variants)) {
583 826 // Take each variant and produce the option markup
584 827 $.each(variants, function (key, el) {
585 - var is_selected = '';
828 + let is_selected = ''
586 829 if (_.isObject(current_val.selected_variants) && inObject(el, current_val.selected_variants)) {
587 - is_selected = ' selected="selected"';
830 + is_selected = ' selected="selected"'
588 831 } else if (_.isString(current_val.selected_variants) && el === current_val.selected_variants) {
589 - is_selected = ' selected="selected"';
832 + is_selected = ' selected="selected"'
590 833 }
591 834
592 835 // initialize
593 - var variant_option_value = el,
594 - variant_option_display = el;
836 + let variant_option_value = el,
837 + variant_option_display = el
595 838
596 839 // If we are dealing with a object variant then it means things get tricky (probably it's our fault but bear with us)
597 840 // This probably comes from our Fonto plugin - a font with individually named variants - hence each has its own font-family
598 841 if (_.isObject(el)) {
599 842 //put the entire object in the variation value - we will need it when outputting the custom CSS
600 - variant_option_value = encodeURIComponent(JSON.stringify(el));
601 - variant_option_display = '';
843 + variant_option_value = encodeURIComponent(JSON.stringify(el))
844 + variant_option_display = ''
602 845
603 846 //if we have weight and style then "compose" them into something standard
604 847 if (!_.isUndefined(el['font-weight'])) {
605 - variant_option_display += el['font-weight'];
848 + variant_option_display += el['font-weight']
606 849 }
607 850
608 - if (_.isString(el['font-style']) && $.inArray(el['font-style'].toLowerCase(), ["normal", "regular"]) < 0) { //this comparison means it hasn't been found
609 - variant_option_display += el['font-style'];
851 + if (_.isString(el['font-style']) && $.inArray(el['font-style'].toLowerCase(), [
852 + 'normal',
853 + 'regular'
854 + ]) < 0) { //this comparison means it hasn't been found
855 + variant_option_display += el['font-style']
610 856 }
611 857 }
612 858
613 - variants_options += '<option value="' + variant_option_value + '"' + is_selected + '>' + variant_option_display + '</option>';
614 - count_weights++;
615 - });
859 + variants_options += '<option value="' + variant_option_value + '"' + is_selected + '>' + variant_option_display + '</option>'
860 + count_weights++
861 + })
616 862 }
617 863
618 - if ( ! _.isUndefined( $font_weight ) ) {
619 - $font_weight.html( variants_options );
864 + if (!_.isUndefined($font_weight)) {
865 + $font_weight.html(variants_options)
620 866 // if there is no weight or just 1 we hide the weight select ... cuz is useless
621 - if ( $( font_select ).data( 'load_all_weights' ) === true || count_weights <= 1 ) {
622 - $font_weight.parent().css( 'display', 'none' );
867 + if ($(font_select).data('load_all_weights') === true || count_weights <= 1) {
868 + $font_weight.parent().css('display', 'none')
623 869 } else {
624 - $font_weight.parent().css( 'display', 'inline-block' );
870 + $font_weight.parent().css('display', 'inline-block')
625 871 }
626 872 }
627 - } else if ( ! _.isUndefined( $font_weight ) ) {
628 - $font_weight.parent().css( 'display', 'none' );
873 + } else if (!_.isUndefined($font_weight)) {
874 + $font_weight.parent().css('display', 'none')
629 875 }
630 876
631 877 // make the subsets selector
632 - if ( ! _.isUndefined( subsets ) && ! _.isNull( subsets ) && ! _.isEmpty( subsets ) ) {
878 + if (!_.isUndefined(subsets) && !_.isNull(subsets) && !_.isEmpty(subsets)) {
633 879
634 - value_to_add['subsets'] = subsets;
880 + value_to_add['subsets'] = subsets
635 881 // when a font is selected force the first subset to load
636 - value_to_add['selected_subsets'] = {0: subsets[0]};
637 - var subsets_options = '',
638 - count_subsets = 0;
639 - $.each( subsets, function( key, el ) {
640 - var is_selected = '';
641 - if ( _.isObject( current_val.selected_subsets ) && inObject( el, current_val.selected_subsets ) ) {
642 - is_selected = ' selected="selected"';
882 + value_to_add['selected_subsets'] = {0: subsets[0]}
883 + let subsets_options = '',
884 + count_subsets = 0
885 + $.each(subsets, function (key, el) {
886 + let is_selected = ''
887 + if (_.isObject(current_val.selected_subsets) && inObject(el, current_val.selected_subsets)) {
888 + is_selected = ' selected="selected"'
643 889 }
644 890
645 - subsets_options += '<option value="' + el + '"' + is_selected + '>' + el + '</option>';
646 - count_subsets++;
647 - } );
891 + subsets_options += '<option value="' + el + '"' + is_selected + '>' + el + '</option>'
892 + count_subsets++
893 + })
648 894
649 - if ( ! _.isUndefined( $font_subsets ) ) {
650 - $font_subsets.html( subsets_options );
895 + if (!_.isUndefined($font_subsets)) {
896 + $font_subsets.html(subsets_options)
651 897
652 898 // if there is no subset or just 1 we hide the subsets select ... cuz is useless
653 - if ( count_subsets <= 1 ) {
654 - $font_subsets.parent().css( 'display', 'none' );
899 + if (count_subsets <= 1) {
900 + $font_subsets.parent().css('display', 'none')
655 901 } else {
656 - $font_subsets.parent().css( 'display', 'inline-block' );
902 + $font_subsets.parent().css('display', 'inline-block')
657 903 }
658 904 }
659 - } else if ( ! _.isUndefined( $font_subsets ) ) {
660 - $font_subsets.parent().css( 'display', 'none' );
905 + } else if (!_.isUndefined($font_subsets)) {
906 + $font_subsets.parent().css('display', 'none')
661 907 }
662 908
663 - $input.val( encodeURIComponent( JSON.stringify( value_to_add ) ) );
909 + $input.val(encodeURIComponent(JSON.stringify(value_to_add)))
664 910 }
665 - };
911 + }
666 912
667 - /**
668 - * Function to check if a value exists in an object
669 - * @param value
670 - * @param obj
671 - * @returns {boolean}
672 - */
673 - var inObject = function( value, obj ) {
674 - for ( var k in obj ) {
675 - if ( !obj.hasOwnProperty( k ) ) continue;
676 - if ( _.isEqual( obj[k], value ) ) {
677 - return true;
913 + /** Modules **/
914 +
915 + const customifyBackgroundJsControl = (
916 + function () {
917 + 'use strict'
918 +
919 + function init () {
920 + // Remove the image button
921 + $('.customize-control-custom_background .remove-image, .customize-control-custom_background .remove-file').unbind('click').on('click', function (e) {
922 + removeImage($(this).parents('.customize-control-custom_background:first'))
923 + preview($(this))
924 + return false
925 + })
926 +
927 + // Upload media button
928 + $('.customize-control-custom_background .background_upload_button').unbind().on('click', function (event) {
929 + addImage(event, $(this).parents('.customize-control-custom_background:first'))
930 + })
931 +
932 + $('.customify_background_select').on('change', function () {
933 + preview($(this))
934 + })
678 935 }
679 - }
680 - return false;
681 - };
682 936
683 - var maybeJsonParse = function( value ) {
684 - var parsed;
937 + // Add a file via the wp.media function
938 + function addImage (event, selector) {
685 939
686 - //try and parse it, with decodeURIComponent
687 - try {
688 - parsed = JSON.parse( decodeURIComponent( value ) );
689 - } catch ( e ) {
940 + event.preventDefault()
690 941
691 - // in case of an error, treat is as a string
692 - parsed = value;
693 - }
942 + var frame
943 + var jQueryel = jQuery(this)
694 944
695 - return parsed;
696 - };
945 + // If the media frame already exists, reopen it.
946 + if (frame) {
947 + frame.open()
948 + return
949 + }
697 950
698 - var customifyBackgroundJsControl = (function() {
699 - "use strict";
951 + // Create the media frame.
952 + frame = wp.media({
953 + multiple: false,
954 + library: {
955 + //type: 'image' //Only allow images
956 + },
957 + // Set the title of the modal.
958 + title: jQueryel.data('choose'),
700 959
701 - var api = wp.customize;
960 + // Customize the submit button.
961 + button: {
962 + // Set the text of the button.
963 + text: jQueryel.data('update')
964 + // Tell the button not to close the modal, since we're
965 + // going to refresh the page when the image is selected.
966 + }
967 + })
702 968
703 - function init() {
704 - // Remove the image button
705 - $( '.customize-control-custom_background .remove-image, .customize-control-custom_background .remove-file' ).unbind( 'click' ).on( 'click', function( e ) {
706 - removeImage( $( this ).parents( '.customize-control-custom_background:first' ) );
707 - preview( $( this ) );
708 - return false;
709 - } );
969 + // When an image is selected, run a callback.
970 + frame.on('select', function () {
971 + // Grab the selected attachment.
972 + const attachment = frame.state().get('selection').first()
973 + frame.close()
710 974
711 - // Upload media button
712 - $( '.customize-control-custom_background .background_upload_button' ).unbind().on( 'click', function( event ) {
713 - addImage( event, $( this ).parents( '.customize-control-custom_background:first' ) );
714 - } );
975 + if (attachment.attributes.type !== 'image') {
976 + return
977 + }
715 978
716 - $( '.customify_background_select' ).on( 'change', function() {
717 - preview( $( this ) );
718 - } );
719 - }
979 + selector.find('.upload').attr('value', attachment.attributes.url)
980 + selector.find('.upload-id').attr('value', attachment.attributes.id)
981 + selector.find('.upload-height').attr('value', attachment.attributes.height)
982 + selector.find('.upload-width').attr('value', attachment.attributes.width)
720 983
721 - // Add a file via the wp.media function
722 - function addImage( event, selector ) {
984 + let thumbSrc = attachment.attributes.url
985 + if (!_.isUndefined(attachment.attributes.sizes) && !_.isUndefined(attachment.attributes.sizes.thumbnail)) {
986 + thumbSrc = attachment.attributes.sizes.thumbnail.url
987 + } else if (!_.isUndefined(attachment.attributes.sizes)) {
988 + let height = attachment.attributes.height
989 + for (let key in attachment.attributes.sizes) {
990 + const object = attachment.attributes.sizes[key]
991 + if (object.height < height) {
992 + height = object.height
993 + thumbSrc = object.url
994 + }
995 + }
996 + } else {
997 + thumbSrc = attachment.attributes.icon
998 + }
723 999
724 - event.preventDefault();
1000 + selector.find('.customify_background_input.background-image').val(attachment.attributes.url)
725 1001
726 - var frame;
727 - var jQueryel = jQuery( this );
1002 + if (!selector.find('.upload').hasClass('noPreview')) {
1003 + selector.find('.preview_screenshot').empty().hide().append('<img class="preview_image" src="' + thumbSrc + '">').slideDown('fast')
1004 + }
1005 + //selector.find('.media_upload_button').unbind();
1006 + selector.find('.remove-image').removeClass('hide')//show "Remove" button
1007 + selector.find('.customify_background_select').removeClass('hide')//show "Remove" button
728 1008
729 - // If the media frame already exists, reopen it.
730 - if ( frame ) {
731 - frame.open();
732 - return;
1009 + preview(selector)
1010 + })
1011 +
1012 + // Finally, open the modal.
1013 + frame.open()
733 1014 }
734 1015
735 - // Create the media frame.
736 - frame = wp.media( {
737 - multiple: false,
738 - library: {
739 - //type: 'image' //Only allow images
740 - },
741 - // Set the title of the modal.
742 - title: jQueryel.data( 'choose' ),
1016 + // Update the background preview
1017 + function preview (selector) {
743 1018
744 - // Customize the submit button.
745 - button: {
746 - // Set the text of the button.
747 - text: jQueryel.data( 'update' )
748 - // Tell the button not to close the modal, since we're
749 - // going to refresh the page when the image is selected.
750 - }
751 - } );
1019 + let $parent = selector.parents('.customize-control-custom_background:first')
752 1020
753 - // When an image is selected, run a callback.
754 - frame.on( 'select', function() {
755 - // Grab the selected attachment.
756 - var attachment = frame.state().get( 'selection' ).first();
757 - frame.close();
758 -
759 - if ( attachment.attributes.type !== "image" ) {
760 - return;
1021 + if (selector.hasClass('customize-control-custom_background')) {
1022 + $parent = selector
761 1023 }
762 1024
763 - selector.find( '.upload' ).attr( 'value', attachment.attributes.url );
764 - selector.find( '.upload-id' ).attr( 'value', attachment.attributes.id );
765 - selector.find( '.upload-height' ).attr( 'value', attachment.attributes.height );
766 - selector.find( '.upload-width' ).attr( 'value', attachment.attributes.width );
767 -
768 - var thumbSrc = attachment.attributes.url;
769 - if ( ! _.isUndefined( attachment.attributes.sizes ) && ! _.isUndefined( attachment.attributes.sizes.thumbnail ) ) {
770 - thumbSrc = attachment.attributes.sizes.thumbnail.url;
771 - } else if ( ! _.isUndefined( attachment.attributes.sizes ) ) {
772 - var height = attachment.attributes.height;
773 - for ( var key in attachment.attributes.sizes ) {
774 - var object = attachment.attributes.sizes[key];
775 - if ( object.height < height ) {
776 - height = object.height;
777 - thumbSrc = object.url;
778 - }
779 - }
1025 + if ($parent.length > 0) {
1026 + $parent = $($parent[0])
780 1027 } else {
781 - thumbSrc = attachment.attributes.icon;
1028 + return
782 1029 }
783 1030
784 - selector.find( '.customify_background_input.background-image' ).val( attachment.attributes.url );
1031 + const image_holder = $parent.find('.background-preview')
785 1032
786 - if ( !selector.find( '.upload' ).hasClass( 'noPreview' ) ) {
787 - selector.find( '.preview_screenshot' ).empty().hide().append( '<img class="preview_image" src="' + thumbSrc + '">' ).slideDown( 'fast' );
1033 + if (!image_holder) { // No preview present
1034 + return
788 1035 }
789 - //selector.find('.media_upload_button').unbind();
790 - selector.find( '.remove-image' ).removeClass( 'hide' );//show "Remove" button
791 - selector.find( '.customify_background_select' ).removeClass( 'hide' );//show "Remove" button
792 1036
793 - preview( selector );
794 - } );
1037 + const the_id = $parent.find('.button.background_upload_button').data('setting_id'),
1038 + this_setting = api.instance(the_id)
795 1039
796 - // Finally, open the modal.
797 - frame.open();
798 - }
1040 + let background_data = {}
799 1041
800 - // Update the background preview
801 - function preview( selector ) {
1042 + $parent.find('.customify_background_select, .customify_background_input').each(function () {
1043 + var data = $(this).serializeArray()
802 1044
803 - var $parent = selector.parents( '.customize-control-custom_background:first' );
1045 + data = data[0]
1046 + if (data && data.name.indexOf('[background-') != -1) {
804 1047
805 - if ( selector.hasClass( 'customize-control-custom_background' ) ) {
806 - $parent = selector;
807 - }
1048 + background_data[$(this).data('select_name')] = data.value
808 1049
809 - if ( $parent.length > 0 ) {
810 - $parent = $( $parent[0] );
811 - } else {
812 - return;
813 - }
1050 + //default_default[data.name] = data.value;
1051 + //if (data.name == "background-image") {
1052 + // css += data.name + ':url("' + data.value + '");';
1053 + //} else {
1054 + // css += data.name + ':' + data.value + ';';
1055 + //}
1056 + }
1057 + })
814 1058
815 - var image_holder = $parent.find( '.background-preview' );
1059 + api.instance(the_id).set(background_data)
1060 + //// Notify the customizer api about this change
1061 + api.trigger('change')
1062 + api.previewer.refresh()
816 1063
817 - if ( !image_holder ) { // No preview present
818 - return;
1064 + //image_holder.attr('style', css).fadeIn();
819 1065 }
820 1066
821 - var the_id = $parent.find( '.button.background_upload_button' ).data( 'setting_id' ),
822 - this_setting = api.instance( the_id );
1067 + // Update the background preview
1068 + function removeImage (parent) {
1069 + const selector = parent.find('.upload_button_div')
1070 + // This shouldn't have been run...
1071 + if (!selector.find('.remove-image').addClass('hide')) {
1072 + return
1073 + }
823 1074
824 - var background_data = {};
1075 + selector.find('.remove-image').addClass('hide')//hide "Remove" button
1076 + parent.find('.customify_background_select').addClass('hide')
825 1077
826 - $parent.find( '.customify_background_select, .customify_background_input' ).each( function() {
827 - var data = $( this ).serializeArray();
1078 + selector.find('.upload').val('')
1079 + selector.find('.upload-id').val('')
1080 + selector.find('.upload-height').val('')
1081 + selector.find('.upload-width').val('')
1082 + parent.find('.customify_background_input.background-image').val('')
828 1083
829 - data = data[0];
830 - if ( data && data.name.indexOf( '[background-' ) != -1 ) {
1084 + let customizer_id = selector.find('.background_upload_button').data('setting_id'),
1085 + this_setting = api.control(customizer_id + '_control'),
1086 + current_vals = this_setting.setting(),
1087 + screenshot = parent.find('.preview_screenshot'),
1088 + to_array = $.map(current_vals, function (value, index) {
1089 + return [value]
1090 + })
831 1091
832 - background_data[$( this ).data( 'select_name' )] = data.value;
1092 + // Hide the screenshot
1093 + screenshot.slideUp()
1094 + selector.find('.remove-file').unbind()
1095 + to_array['background-image'] = ''
1096 + this_setting.setting(to_array)
1097 + }
833 1098
834 - //default_default[data.name] = data.value;
835 - //if (data.name == "background-image") {
836 - // css += data.name + ':url("' + data.value + '");';
837 - //} else {
838 - // css += data.name + ':' + data.value + ';';
839 - //}
840 - }
841 - } );
842 -
843 - api.instance( the_id ).set( background_data );
844 - //// Notify the customizer api about this change
845 - api.trigger( 'change' );
846 - api.previewer.refresh();
847 -
848 - //image_holder.attr('style', css).fadeIn();
849 - }
850 -
851 - // Update the background preview
852 - function removeImage( parent ) {
853 - var selector = parent.find( '.upload_button_div' );
854 - // This shouldn't have been run...
855 - if ( !selector.find( '.remove-image' ).addClass( 'hide' ) ) {
856 - return;
1099 + return {
1100 + init: init
857 1101 }
858 -
859 - selector.find( '.remove-image' ).addClass( 'hide' );//hide "Remove" button
860 - parent.find( '.customify_background_select' ).addClass( 'hide' );
861 -
862 - selector.find( '.upload' ).val( '' );
863 - selector.find( '.upload-id' ).val( '' );
864 - selector.find( '.upload-height' ).val( '' );
865 - selector.find( '.upload-width' ).val( '' );
866 - parent.find( '.customify_background_input.background-image' ).val( '' );
867 -
868 - var customizer_id = selector.find( '.background_upload_button' ).data( 'setting_id' ),
869 - this_setting = api.control( customizer_id + '_control' ),
870 - current_vals = this_setting.setting(),
871 - screenshot = parent.find( '.preview_screenshot' ),
872 - to_array = $.map( current_vals, function( value, index ) {
873 - return [value];
874 - } );
875 -
876 - // Hide the screenshot
877 - screenshot.slideUp();
878 - selector.find( '.remove-file' ).unbind();
879 - to_array['background-image'] = '';
880 - this_setting.setting( to_array );
881 1102 }
1103 + )(jQuery)
882 1104
883 - return {
884 - init: init
885 - }
886 - })( jQuery );
1105 + /** HELPERS **/
887 1106
888 - var getUrlVars = function( name ) {
889 - var vars = [], hash;
890 - var hashes = window.location.href.slice( window.location.href.indexOf( '?' ) + 1 ).split( '&' );
891 - for ( var i = 0; i < hashes.length; i++ ) {
892 - hash = hashes[i].split( '=' );
893 -
894 - vars.push( hash[0] );
895 - vars[hash[0]] = hash[1];
1107 + /**
1108 + * Function to check if a value exists in an object
1109 + * @param value
1110 + * @param obj
1111 + * @returns {boolean}
1112 + */
1113 + const inObject = function (value, obj) {
1114 + for (let k in obj) {
1115 + if (!obj.hasOwnProperty(k)) {
1116 + continue
1117 + }
1118 + if (_.isEqual(obj[k], value)) {
1119 + return true
1120 + }
896 1121 }
1122 + return false
1123 + }
897 1124
898 - if ( ! _.isUndefined( vars[name] ) ) {
899 - return vars[name];
900 - }
901 - return false;
902 - };
1125 + const maybeJsonParse = function (value) {
1126 + let parsed
903 1127
904 - var isJsonString = function( str ) {
1128 + //try and parse it, with decodeURIComponent
905 1129 try {
906 - JSON.parse( str );
907 - } catch ( e ) {
908 - return false;
909 - }
910 - return true;
911 - };
912 - } );
1130 + parsed = JSON.parse(decodeURIComponent(value))
1131 + } catch (e) {
913 1132
914 - var Queue = function() {
915 - var lastPromise = null;
916 - var queueDeferred = null;
917 - var methodDeferred = null;
918 -
919 - this.add_steps = function( key, steps, args ) {
920 - var self = this;
921 - this.methodDeferred = $.Deferred();
922 - this.queueDeferred = this.setup();
923 -
924 - $.each( steps, function( i, step ) {
925 - self.queue( key, step );
926 - } );
927 - };
928 -
929 - this.process_remote_step = function( key, data, step ) {
930 - var self = this;
931 -
932 - if ( _.isUndefined( data ) || _.isNull( data ) ) {
933 - return false;
1133 + // in case of an error, treat is as a string
1134 + parsed = value
934 1135 }
935 1136
936 - var new_step = step;
937 - $.each( data, function( i, k ) {
938 -debugger;
939 - // prepare data for new requests
940 - new_step.recall_data = k.data;
941 - new_step.recall_type = k.type;
942 - new_step.type = 'recall';
1137 + return parsed
1138 + }
943 1139
944 - self.queue( key, new_step, k.id );
945 - } );
946 - };
1140 + const getUrlVars = function (name) {
1141 + let vars = [], hash
1142 + const hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&')
1143 + for (let i = 0; i < hashes.length; i++) {
1144 + hash = hashes[i].split('=')
947 1145
948 - this.log_action = function( action, key, msg ) {
949 - if ( action === 'start' ) {
950 - $('.wpGrade-import-results' ).show();
951 - $('.wpGrade-import-results' ).append( '<span class="import_step_note imports_step_' + key + '" ><span class="step_info" data-balloon="Working on it" data-balloon-pos="up"></span>Importing ' + key + '</span>' );
952 - } else if ( action === 'end' ) {
953 - var $notice = $('.imports_step_' + key + ' .step_info');
954 -
955 - if ( $notice.length > 0 || msg !== "undefined") {
956 - $notice.attr('data-balloon', msg);
957 - $notice.addClass('success');
958 - } else {
959 - $notice.attr('data-balloon', 'Done');
960 - $notice.addClass('failed');
961 - }
1146 + vars.push(hash[0])
1147 + vars[hash[0]] = hash[1]
962 1148 }
963 - };
964 1149
965 - this.queue = function( key, data, step_key ) {
966 - var self = this;
967 - if ( ! _.isUndefined( step_key ) ) {
968 - this.log_action( 'start', step_key );
1150 + if (!_.isUndefined(vars[name])) {
1151 + return vars[name]
969 1152 }
1153 + return false
1154 + }
970 1155
971 - // execute next queue method
972 - this.queueDeferred.done( this.request( key, data, step_key ) );
973 - lastPromise = self.methodDeferred.promise();
974 - };
975 -
976 - this.request = function( key, step, step_key ) {
977 - var self = this;
978 - // call actual method and wrap output in deferred
979 - //setTimeout( function() {
980 - var data_args = {
981 - action: 'customify_import_step',
982 - step_id: step.id,
983 - step_type: step.type,
984 - option_key: key
985 - };
986 -
987 - if ( ! _.isUndefined( step.recall_data ) ) {
988 - data_args.recall_data = step.recall_data;
1156 + const isJsonString = function (str) {
1157 + try {
1158 + JSON.parse(str)
1159 + } catch (e) {
1160 + return false
989 1161 }
990 -
991 - if ( ! _.isUndefined( step.recall_type ) ) {
992 - data_args.recall_type = step.recall_type;
993 - }
994 -
995 - $.ajax( {
996 - url: customify_settings.import_rest_url + 'customify/1.0/import',
997 - method: 'POST',
998 - beforeSend: function( xhr ) {
999 - xhr.setRequestHeader( 'X-WP-Nonce', WP_API_Settings.nonce );
1000 - },
1001 - dataType: 'json',
1002 - contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
1003 - data: data_args
1004 - } ).done( function( response ) {
1005 - if ( ! _.isUndefined( response.success ) && response.success ) {
1006 - var results = response.data;
1007 - if ( step.type === 'remote' ) {
1008 - self.process_remote_step( key, results, step );
1009 - }
1010 - }
1011 -
1012 - if ( ! _.isUndefined( step_key ) && ! _.isUndefined( response.message ) ) {
1013 - self.log_action( 'end', step_key, response.message );
1014 - }
1015 - } );
1016 -
1017 - self.methodDeferred.resolve();
1018 - //}, 3450 );
1019 - };
1020 -
1021 - this.setup = function() {
1022 - var self = this;
1023 -
1024 - self.queueDeferred = $.Deferred();
1025 -
1026 - // when the previous method returns, resolve this one
1027 - $.when( lastPromise ).always( function() {
1028 - self.queueDeferred.resolve();
1029 - } );
1030 -
1031 - return self.queueDeferred.promise();
1162 + return true
1032 1163 }
1033 - };
1034 -
1035 -})( jQuery, window );
1164 + }
1165 +)(jQuery, window, wp)