PluginProbe
Customify / 1.2.4
Customify v1.2.4
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 1.2.4, at js/customizer.js

1,036 lines 32.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function( $, exports ) {
2 $( document ).ready( function() {
3 // when the customizer is ready prepare our fields events
4 wp.customize.bind( 'ready', function() {
5 var api = this,
6 timeout = null;
7
8 // add ace editors
9 $( '.customify_ace_editor' ).each( function( key, el ) {
10 var id = $( this ).attr( 'id' ),
11 css_editor = ace.edit( id );
12
13 var editor_type = $( this ).data( 'editor_type' );
14 // init the ace editor
15 css_editor.setTheme( "ace/theme/github" );
16 css_editor.getSession().setMode( "ace/mode/" + editor_type );
17
18 // hide the textarea and enable the ace editor
19 var textarea = $( '#' + id + '_textarea' ).hide();
20 css_editor.getSession().setValue( textarea.val() );
21
22 // each time a change is triggered start a timeout of 1,5s and when is finished refresh the previewer
23 // 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;
28 } else {
29 timeout = setTimeout( function() {
30 //var state = css_editor.session.getState();
31 textarea.val( css_editor.getSession().getValue() );
32 textarea.trigger( 'change' );
33 }, 1500 );
34 }
35 } );
36 } );
37
38 // simple select2 field
39 $( '.customify_select2' ).select2();
40
41 prepare_typography_field();
42
43 /**
44 * Make the customizer save on CMD/CTRL+S action
45 * This is awesome!!!
46 */
47 $( window ).bind( 'keydown', function( event ) {
48 if ( event.ctrlKey || event.metaKey ) {
49 switch ( String.fromCharCode( event.which ).toLowerCase() ) {
50 case 's':
51 event.preventDefault();
52 api.previewer.save();
53 break;
54 }
55 }
56 } );
57
58 // for each range input add a value preview output
59 $( 'input[type="range"]' ).each( function() {
60 var $clone = $( this ).clone();
61
62 $clone
63 .attr( 'type', 'number' )
64 .attr( 'class', 'range-value' );
65
66 $( this ).after( $clone );
67
68 $( this ).on( 'input', function() {
69 $( this ).siblings( '.range-value' ).val( $( this ).val() );
70 } );
71 } );
72
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();
77
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!' );
79
80 if ( !iAgree ) {
81 return;
82 }
83
84 $.each( api.settings.controls, function( key, ctrl ) {
85 var id = key.replace( '_control', '' );
86 var setting = customify_settings.settings[id];
87
88 if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
89
90 var start_pos = id.indexOf( '[' ) + 1;
91 var end_pos = id.indexOf( ']', start_pos );
92
93 id = id.substring( start_pos, end_pos );
94 api_set_setting_value( id, setting.default );
95 }
96 } );
97
98 api.previewer.save();
99 } );
100
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-', '' );
106
107
108 $( this ).parent().append( '<button class="reset_panel button" data-panel="' + panel_id + '">Panel\'s defaults</button>' );
109 } );
110
111 // reset panel
112 $( document ).on( 'click', '.reset_panel', function( e ) {
113 e.preventDefault();
114
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 + "?" );
119
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();
127
128 if ( controls.length > 0 ) {
129 $.each( controls, function( key, ctrl ) {
130 var id = ctrl.id.replace( '_control', '' ),
131 setting = customify_settings.settings[id];
132
133 if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
134
135 var start_pos = id.indexOf( '[' ) + 1,
136 end_pos = id.indexOf( ']', start_pos );
137
138 id = id.substring( start_pos, end_pos );
139 api_set_setting_value( id, setting.default );
140 }
141 } );
142 }
143 } );
144 }
145 } );
146
147 //add reset section
148 $( '.accordion-section-content' ).each( function( el, key ) {
149 var section = $( this ).parent(),
150 section_id = section.attr( 'id' );
151
152 if ( ( ( ! _.isUndefined( section_id ) ) ? section_id.indexOf( customify_settings.options_name ) : -1 ) === -1 ) {
153 return;
154 }
155
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 } );
161
162 // reset section event
163 $( document ).on( 'click', '.reset_section', function( e ) {
164 e.preventDefault();
165
166 var section_id = $( this ).data( 'section' ),
167 section = api.section( section_id ),
168 controls = section.controls();
169
170 var iAgree = confirm( "Do you really want to reset " + section.params.title + "?" );
171
172 if ( !iAgree ) {
173 return;
174 }
175
176 if ( controls.length > 0 ) {
177 $.each( controls, function( key, ctrl ) {
178 var id = ctrl.id.replace( '_control', '' ),
179 setting = customify_settings.settings[id];
180
181 if ( ! _.isUndefined( setting ) && ! _.isUndefined( setting.default ) ) {
182
183 var start_pos = id.indexOf( '[' ) + 1,
184 end_pos = id.indexOf( ']', start_pos );
185
186 id = id.substring( start_pos, end_pos );
187 api_set_setting_value( id, setting.default );
188 }
189 } );
190 }
191 } );
192 }
193
194 $( document ).on( 'change', '.customize-control input.range-value', function() {
195 var range = $( this ).siblings( 'input[type="range"]' );
196 range.val( $( this ).val() );
197 } );
198
199 $( document ).on( 'change', '.customify_typography_font_subsets', function( ev ) {
200
201 var $input = $( this ).parents( '.options' ).siblings( '.customify_typography' ).children( '.customify_typography_values' ),
202 current_val = $input.val();
203
204 current_val = JSON.parse( decodeURIComponent( current_val ) );
205
206 //maybe the selected option holds a JSON in its value
207 current_val.selected_subsets = maybeJsonParse( $( this ).val() );
208
209 $input.val( encodeURIComponent( JSON.stringify( current_val ) ) );
210
211 $input.trigger( 'change' );
212 } );
213
214 $( document ).on( 'change', '.customify_typography_font_weight', function( ev ) {
215
216 var $input = $( this ).parents( '.options' ).siblings( '.customify_typography' ).children( '.customify_typography_values' ),
217 current_val = $input.val();
218
219 current_val = maybeJsonParse( current_val );
220 // @todo currently the font weight selector works for one value only
221 // maybe make this a multiselect
222
223 //maybe the selected option holds a JSON in its value
224 current_val.selected_variants = {0: maybeJsonParse( $( this ).val() ) };
225
226 $input.val( encodeURIComponent( JSON.stringify( current_val ) ) );
227 $input.trigger( 'change' );
228 } );
229
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' );
235
236 if ( ! _.isUndefined( data ) ) {
237 $.each( data, function( id, value ) {
238 api_set_setting_value( id, value );
239 } );
240 }
241
242 api.previewer.refresh();
243 } );
244
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' );
249
250 if ( ! _.isUndefined( data ) ) {
251 $.each( data, function( id, value ) {
252 api_set_setting_value( id, value );
253 } );
254 }
255
256 api.previewer.refresh();
257 } );
258
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;
269
270 //@todo start an animation here
271 var key = $( this ).data( 'key' );
272
273 var import_queue = new Queue( api );
274
275 /// calculate the number of steps
276 var steps = [];
277
278 if ( ! _.isUndefined( customify_settings.settings[key].imports ) ) {
279
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;
285
286 while ( count >= 1 ) {
287 steps.push( {id: i, type: import_setts.type, count: count} );
288 count = count - 1;
289 }
290 }
291 } );
292 }
293
294 import_queue.add_steps( 'import_demo_data_action_id', steps );
295 return false;
296 } );
297
298 customifyBackgroundJsControl.init();
299
300 // sometimes there may be needed a php save
301 if ( getUrlVars( 'save_customizer_once' ) ) {
302 api.previewer.save();
303 }
304
305 setTimeout(function () {
306 customifyFoldingFields();
307 }, 1000);
308 } );
309
310 /**
311 * This function will search for all the interdependend fields and make a bound between them.
312 * So whenever a target is changed, it will take actions to the dependent fields.
313 */
314 var customifyFoldingFields = function() {
315
316 if ( _.isUndefined( customify_settings ) || _.isUndefined( customify_settings.settings ) ) {
317 return ; // bail
318 }
319
320 /**
321 * Let's iterate through all the customify settings and gather all the fields that have a "show_on"
322 * property set.
323 *
324 * At the end `targets` will hold a list of [ target : [field, field,...], ... ]
325 * so when a target is changed we will change all the fields.
326 */
327 var targets = {};
328
329 $.fn.reactor.defaults.compliant = function() {
330 $(this).slideDown();
331 // $(this).animate({opacity: 1});
332 $(this).find(':disabled').attr({disabled: false});
333 };
334
335 $.fn.reactor.defaults.uncompliant = function() {
336 $(this).slideUp();
337 // $(this).animate({opacity: 0.25});
338 $(this).find(':enabled').attr({disabled: true});
339 };
340
341 var IS = $.extend({}, $.fn.reactor.helpers);
342
343 var process_a_target = function( parent_id, field ) {
344
345 if ( _.isUndefined( field[0] ) ) {
346 return ; // no id, no fun
347 }
348
349 var key = field[0],
350 value = 1, // by default we use 1 the most used value for checboxes or inputs
351 compare = '==', // ... ye
352 action = "show"; // can only be `show` or `hide`
353
354 var target_key = customify_settings.options_name + '[' + key + ']';
355 var target_type = customify_settings.settings[ target_key ].type;
356
357
358 if ( ! _.isUndefined( field[1] ) ) {
359 value = field[1];
360 }
361
362 if ( ! _.isUndefined( field[2] ) ) {
363 compare = field[2];
364 }
365
366 if ( ! _.isUndefined( field[3] ) ) {
367 action = field[3];
368 }
369
370 /**
371 * Now for each target we have, we will bind a change event to hide or show the dependent fields
372 */
373 var target_selector = '[data-customize-setting-link="' + customify_settings.options_name + '[' + key + ']"]';
374
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 } );
389 }
390
391 $(target_selector).trigger('change');
392 $('.reactor').trigger('change.reactor'); // triggers all events on load
393 };
394
395 $.each( customify_settings.settings, function ( id, field ) {
396
397 /**
398 * Here we have the id of the fields. but we know for sure that we just need his parent selector
399 * So we just create it
400 */
401 var parent_id = id.replace( '[', '-' );
402 parent_id = parent_id.replace( ']', '' );
403 parent_id = '#customize-control-' + parent_id + '_control';
404
405
406 // get only the fields that have a 'show_on' property
407 if ( field.hasOwnProperty( 'show_on' ) && field.show_on.length > 0 ) {
408
409 /**
410 * The 'show_on' can be a simple array with one target like: [ id, value, comparison, action ]
411 * Or it could be an array of multiple targets and we need to process both cases
412 */
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 });
419 }
420 }
421 });
422 };
423
424 var get_typography_font_family = function( $el ) {
425
426 var font_family_value = $el.val();
427 // first time this will not be a json so catch that error
428 try {
429 font_family_value = JSON.parse( font_family_value );
430 } catch ( e ) {
431 return {font_family: font_family_value};
432 }
433
434 if ( ! _.isUndefined( font_family_value.font_family ) ) {
435 return font_family_value.font_family;
436 }
437
438 return false;
439 };
440
441 // get each typography field and bind events
442 var prepare_typography_field = function() {
443
444 var $typos = $( '.customify_typography_font_family' );
445
446 $typos.each( function() {
447 var font_family_select = this,
448 $input = $( font_family_select ).siblings( '.customify_typography_values' );
449 // 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 };
457
458 var api_set_setting_value = function( id, value ) {
459
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' );
465
466 if ( ! _.isUndefined( field_class ) && field_class === 'customify_typography' ) {
467
468 var family_select = field.siblings( 'select' );
469
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' );
477
478 update_siblings_selects( this_family_option );
479
480 setTimeout( function() {
481 var weight_select = field.parent().siblings( '.options' ).find( '.customify_typography_font_weight' );
482
483 var this_weight_option = weight_select.find( 'option[value="' + value['selected_variants'] + '"]' );
484
485 $( this_weight_option[0] ).attr( 'selected', 'selected' );
486
487 update_siblings_selects( this_family_option );
488
489 weight_select.trigger( 'change' );
490 }, 300 );
491 }
492
493 family_select.trigger( 'change' );
494
495 } else {
496 setting.set( value );
497 }
498 };
499
500 var update_siblings_selects = function( font_select ) {
501
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) == '[' ) {
510 // 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];
515 }
516
517 if ( ! _.isUndefined( current_val[1] ) ) {
518 new_current_value['selected_variants'] = current_val[1];
519 }
520
521 current_val = JSON.stringify( new_current_value );
522 }
523
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' );
526
527 try {
528 current_val = JSON.parse( decodeURIComponent( current_val ) );
529 } catch ( e ) {
530
531 // in case of an error, force the rebuild of the json
532 if ( _.isUndefined( $( font_select ).data( 'bound_once' ) ) ) {
533
534 $( font_select ).data( 'bound_once', true );
535 //var api = wp.customize;
536 //api.previewer.refresh();
537
538 $( font_select ).change();
539 $font_weight.change();
540 $font_subsets.change();
541 }
542 }
543
544 // 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 + '"]' );
546 // 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 + '"]' );
549 }
550
551 if ( option_data.length > 0 ) {
552
553 var font_type = option_data.data( 'type' ),
554 value_to_add = {'type': font_type, 'font_family': selected_font},
555 variants = null,
556 subsets = null;
557
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' ) ) ) {
561 //maybe the variants are a JSON
562 variants = maybeJsonParse( $( option_data[0] ).data( 'variants' ) );
563 }
564 } else {
565 //maybe the variants are a JSON
566 variants = maybeJsonParse( $( option_data[0] ).data( 'variants' ) );
567
568 //maybe the subsets are a JSON
569 subsets = maybeJsonParse( $( option_data[0] ).data( 'subsets' ) );
570 }
571
572 // make the variants selector
573 if ( ! _.isUndefined( variants ) && ! _.isNull( variants ) && ! _.isEmpty( variants ) ) {
574
575 value_to_add['variants'] = variants;
576 // when a font is selected force the first weight to load
577 value_to_add['selected_variants'] = {0: variants[0]};
578
579 var variants_options = '',
580 count_weights = 0;
581
582 if ( _.isArray( variants ) || _.isObject( variants ) ) {
583 // Take each variant and produce the option markup
584 $.each(variants, function (key, el) {
585 var is_selected = '';
586 if (_.isObject(current_val.selected_variants) && inObject(el, current_val.selected_variants)) {
587 is_selected = ' selected="selected"';
588 } else if (_.isString(current_val.selected_variants) && el === current_val.selected_variants) {
589 is_selected = ' selected="selected"';
590 }
591
592 // initialize
593 var variant_option_value = el,
594 variant_option_display = el;
595
596 // If we are dealing with a object variant then it means things get tricky (probably it's our fault but bear with us)
597 // This probably comes from our Fonto plugin - a font with individually named variants - hence each has its own font-family
598 if (_.isObject(el)) {
599 //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 = '';
602
603 //if we have weight and style then "compose" them into something standard
604 if (!_.isUndefined(el['font-weight'])) {
605 variant_option_display += el['font-weight'];
606 }
607
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'];
610 }
611 }
612
613 variants_options += '<option value="' + variant_option_value + '"' + is_selected + '>' + variant_option_display + '</option>';
614 count_weights++;
615 });
616 }
617
618 if ( ! _.isUndefined( $font_weight ) ) {
619 $font_weight.html( variants_options );
620 // 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' );
623 } else {
624 $font_weight.parent().css( 'display', 'inline-block' );
625 }
626 }
627 } else if ( ! _.isUndefined( $font_weight ) ) {
628 $font_weight.parent().css( 'display', 'none' );
629 }
630
631 // make the subsets selector
632 if ( ! _.isUndefined( subsets ) && ! _.isNull( subsets ) && ! _.isEmpty( subsets ) ) {
633
634 value_to_add['subsets'] = subsets;
635 // 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"';
643 }
644
645 subsets_options += '<option value="' + el + '"' + is_selected + '>' + el + '</option>';
646 count_subsets++;
647 } );
648
649 if ( ! _.isUndefined( $font_subsets ) ) {
650 $font_subsets.html( subsets_options );
651
652 // 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' );
655 } else {
656 $font_subsets.parent().css( 'display', 'inline-block' );
657 }
658 }
659 } else if ( ! _.isUndefined( $font_subsets ) ) {
660 $font_subsets.parent().css( 'display', 'none' );
661 }
662
663 $input.val( encodeURIComponent( JSON.stringify( value_to_add ) ) );
664 }
665 };
666
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;
678 }
679 }
680 return false;
681 };
682
683 var maybeJsonParse = function( value ) {
684 var parsed;
685
686 //try and parse it, with decodeURIComponent
687 try {
688 parsed = JSON.parse( decodeURIComponent( value ) );
689 } catch ( e ) {
690
691 // in case of an error, treat is as a string
692 parsed = value;
693 }
694
695 return parsed;
696 };
697
698 var customifyBackgroundJsControl = (function() {
699 "use strict";
700
701 var api = wp.customize;
702
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 } );
710
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 } );
715
716 $( '.customify_background_select' ).on( 'change', function() {
717 preview( $( this ) );
718 } );
719 }
720
721 // Add a file via the wp.media function
722 function addImage( event, selector ) {
723
724 event.preventDefault();
725
726 var frame;
727 var jQueryel = jQuery( this );
728
729 // If the media frame already exists, reopen it.
730 if ( frame ) {
731 frame.open();
732 return;
733 }
734
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' ),
743
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 } );
752
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;
761 }
762
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 }
780 } else {
781 thumbSrc = attachment.attributes.icon;
782 }
783
784 selector.find( '.customify_background_input.background-image' ).val( attachment.attributes.url );
785
786 if ( !selector.find( '.upload' ).hasClass( 'noPreview' ) ) {
787 selector.find( '.preview_screenshot' ).empty().hide().append( '<img class="preview_image" src="' + thumbSrc + '">' ).slideDown( 'fast' );
788 }
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
793 preview( selector );
794 } );
795
796 // Finally, open the modal.
797 frame.open();
798 }
799
800 // Update the background preview
801 function preview( selector ) {
802
803 var $parent = selector.parents( '.customize-control-custom_background:first' );
804
805 if ( selector.hasClass( 'customize-control-custom_background' ) ) {
806 $parent = selector;
807 }
808
809 if ( $parent.length > 0 ) {
810 $parent = $( $parent[0] );
811 } else {
812 return;
813 }
814
815 var image_holder = $parent.find( '.background-preview' );
816
817 if ( !image_holder ) { // No preview present
818 return;
819 }
820
821 var the_id = $parent.find( '.button.background_upload_button' ).data( 'setting_id' ),
822 this_setting = api.instance( the_id );
823
824 var background_data = {};
825
826 $parent.find( '.customify_background_select, .customify_background_input' ).each( function() {
827 var data = $( this ).serializeArray();
828
829 data = data[0];
830 if ( data && data.name.indexOf( '[background-' ) != -1 ) {
831
832 background_data[$( this ).data( 'select_name' )] = data.value;
833
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;
857 }
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 }
882
883 return {
884 init: init
885 }
886 })( jQuery );
887
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];
896 }
897
898 if ( ! _.isUndefined( vars[name] ) ) {
899 return vars[name];
900 }
901 return false;
902 };
903
904 var isJsonString = function( str ) {
905 try {
906 JSON.parse( str );
907 } catch ( e ) {
908 return false;
909 }
910 return true;
911 };
912 } );
913
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;
934 }
935
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';
943
944 self.queue( key, new_step, k.id );
945 } );
946 };
947
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 }
962 }
963 };
964
965 this.queue = function( key, data, step_key ) {
966 var self = this;
967 if ( ! _.isUndefined( step_key ) ) {
968 this.log_action( 'start', step_key );
969 }
970
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;
989 }
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();
1032 }
1033 };
1034
1035 })( jQuery, window );
1036