wp.customize.controlConstructor['clelement'] = wp.customize.Control.extend({ ready: function() { 'use strict'; var control = this, limit; this.element_values = {}; this.element_id = this.container.data('id'); this.selects = []; this.active.set(false); // The DIV that holds all the rows this.elementsFieldsContainer = this.container.find( '.fields' ).first(); // Set number of rows to 0 this.currentIndex = 0; // Default limit choice limit = false; if ( undefined !== this.params.choices.limit ) { limit = ( 0 >= this.params.choices.limit ) ? false : parseInt( this.params.choices.limit ); } this.buildDependeciens(); this.container.on( 'click keypress', '.element-field-image .upload-button,.element-field-cropped_image .upload-button,.element-field-upload .upload-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.openFrame( e ); }); this.container.on( 'click keypress', '.element-field-image .remove-button,.element-field-cropped_image .remove-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.removeImage( e ); }); this.container.on( 'click keypress', '.element-field-upload .remove-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.removeFile( e ); }); /**/ /*this.container.on('mousemove', 'input[type=range]', function(e) { });*/ /*this.container.on('focusout', 'input[type="text"]', function(e){ control.setting.previewer.send('cl_focusout', 'cl_header_menu-1'); });*/ /** * Function that loads the Mustache template */ this.elementTemplate = _.memoize( function( element_id ) { var compiled, /* * Underscore's default ERB-style templates are incompatible with PHP * when asp_tags is enabled, so WordPress uses Mustache-inspired templating syntax. * * @see trac ticket #22344. */ options = { evaluate: /<#([\s\S]+?)#>/g, interpolate: /\{\{\{([\s\S]+?)\}\}\}/g, escape: /\{\{([^\}]+?)\}\}(?!\})/g, variable: 'data' }; return function( data ) { compiled = _.template( jQuery( '#tmpl-customize-control-'+element_id+'-content' ).first().html(), null, options ); return compiled( data ); }; }); // When we load the control, the fields have not been filled up // This is the first time that we create all the rows //this.createEl(); }, galleryReady: function(id){ var control = this; // Shortcut so that we don't have to use _.bind every time we add a callback. _.bindAll( control, 'galleryOpenFrame', 'gallerySelect' ); /** * Set gallery data and render content. */ // Ensure attachment data is initially set. control.setGalleryDataAndRenderContent(id); // Bind events. control.container.on( 'click keydown', '.upload-button', control.galleryOpenFrame ); }, setGalleryDataAndRenderContent: function(id) { var control = this; var value = control.getValue(); if( value[id].length ) value = JSON.parse( value[id].replace('__array__', '[').replace('__array__end__', ']') ); else value = []; control.openedGallery = id; control.gallerySetAttachmentsData( value ).done( function() { control.galleryRenderAttachments(); control.gallerySetupSortable(); } ); }, galleryRenderAttachments: function(){ var inner_container, control; control = this; inner_container = control.container.find('[data-field="'+control.openedGallery+'"]').closest('.image-gallery-attachments'); inner_container.html(''); _.each(control.codelessElementMap[control.openedGallery].attachments, function(attachment){ inner_container.append(''); } ); control.gallerySetupSortable(); }, /** * Open the media modal. */ galleryOpenFrame: function( event ) { event.preventDefault(); if ( ! this.frame ) { this.galleryInitFrame(); } this.frame.open(); }, /** * Initiate the media modal select frame. * Save it for using later in case needed. */ galleryInitFrame: function() { var control = this, galleryPreSelectImages; this.frame = wp.media({ button: { text: 'Choose Images' }, states: [ new wp.media.controller.Library({ title: 'Select Gallery Images', library: wp.media.query({ type: 'image' }), multiple: 'add' }) ] }); /** * Pre-select images according to saved settings. */ galleryPreSelectImages = function() { var selection, ids, attachment, library; library = control.frame.state().get( 'library' ); selection = control.frame.state().get( 'selection' ); ids = control.getValue(); if( ids[control.openedGallery].length ) ids = JSON.parse( ids[control.openedGallery].replace('{', '[').replace('}', ']') ); else ids = []; // Sort the selected images to top when opening media modal. library.comparator = function( a, b ) { var hasA = true === this.mirroring.get( a.cid ), hasB = true === this.mirroring.get( b.cid ); if ( ! hasA && hasB ) { return -1; } else if ( hasA && ! hasB ) { return 1; } else { return 0; } }; _.each( ids, function( id ) { attachment = wp.media.attachment( id ); selection.add( attachment ? [ attachment ] : [] ); library.add( attachment ? [ attachment ] : [] ); }); }; control.frame.on( 'open', galleryPreSelectImages ); control.frame.on( 'select', control.gallerySelect ); }, /** * Callback for selecting attachments. */ gallerySelect: function() { var control = this, attachments, attachmentIds, fieldId, currentSettings; attachments = control.frame.state().get( 'selection' ).toJSON(); control.codelessElementMap[control.openedGallery].attachments = attachments; attachmentIds = control.galleryGetAttachmentIds( attachments ); fieldId = control.container.find('.image-gallery-attachments').data('field'); currentSettings = this.getValue(); currentSettings[ fieldId ] = JSON.stringify(attachmentIds).replace('[', '__array__').replace(']', '__array__end__'); control.setValue( currentSettings, true, false, fieldId, 'image_gallery', '', ''); control.container.focus(); control.setGalleryDataAndRenderContent(fieldId); }, /** * Get array of attachment id-s from attachment objects. * * @param {Array} attachments Attachments. * @returns {Array} */ galleryGetAttachmentIds: function( attachments ) { var ids = [], i; for ( i in attachments ) { ids.push( attachments[ i ].id ); } return ids; }, gallerySetAttachmentsData: function( value ) { var control = this, promises = []; control.codelessElementMap[control.openedGallery].attachments = []; _.each( value, function( id, index ) { var hasAttachmentData = new jQuery.Deferred(); wp.media.attachment( id ).fetch().done( function() { control.codelessElementMap[control.openedGallery].attachments[ index ] = this.attributes; hasAttachmentData.resolve(); } ); promises.push( hasAttachmentData ); } ); return jQuery.when.apply( undefined, promises ).promise(); }, gallerySetupSortable: function() { var control = this, list = jQuery( '.image-gallery-attachments' ); list.sortable({ items: '.image-gallery-thumbnail-wrapper', tolerance: 'pointer', stop: function() { var selectedValues = []; list.find( '.image-gallery-thumbnail-wrapper' ).each( function() { var id; id = parseInt( jQuery( this ).data( 'postId' ), 10 ); selectedValues.push( id ); } ); var fieldId = control.container.find('.image-gallery-attachments').data('field'); var currentSettings = control.getValue(); currentSettings[ fieldId ] = JSON.stringify(selectedValues).replace('[', '__array__').replace(']', '__array__end__'); control.setValue( currentSettings, true, false, fieldId, 'image_gallery', '', ''); } }); }, buildDependeciens: function(){ this.active_callback = {}; var control = this; if(_.isUndefined(control.cl_required)) control.cl_required = {}; _.each(control.codelessElementMap, function(field, key){ if(!_.isUndefined(field['cl_required']) && field['cl_required'].length){ _.each(field['cl_required'], function(req, index){ if(_.isUndefined(control.cl_required[req['setting']])) control.cl_required[req['setting']] = []; var opt = req['setting']; req['setting'] = key; control.cl_required[opt].push(req); }); } }); }, createEl: function(data, first){ var control = this; if(first){ this.final_value = ''; this.element_id = data.id; this.codelessElementMap = codelessElementsMap[data.id]; } this.addElements(data.options); var control = this; control.initColorPicker(); control.initSelect(); _.each( control.codelessElementMap, function( subValue, index ){ console.log(index); console.log(control.element_values); control.checkDependecies(index, control.element_values[index]); } ); this.activeTabs(); this.container.on( 'click', '.change_icon', function(e){ e.preventDefault(); if(jQuery(this).parent().find('.icons_div').hasClass('hidden')) jQuery(this).parent().find('.icons_div').removeClass('hidden'); else jQuery(this).parent().find('.icons_div').addClass('hidden'); }); this.container.on( 'click keypress', '.element-field-image .upload-button,.element-field-cropped_image .upload-button,.element-field-upload .upload-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.openFrame( e ); }); this.container.on( 'click keypress', '.element-field-image .remove-button,.element-field-cropped_image .remove-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.removeImage( e ); }); this.container.on( 'click keypress', '.element-field-upload .remove-button', function( e ) { e.preventDefault(); control.$thisButton = jQuery( this ); control.removeFile( e ); }); var typingTimer; var doneTypingInterval = 1000; this.container.on( 'change input keyup ', 'input, select, textarea', function( e ) { var element = jQuery( this ); if( jQuery(e.target).closest('span.value').length > 0 ) return true; if( jQuery(e.target).closest('.element-field-css_tool').length == 0 && ( jQuery(e.target).is('[multiple="multiple"]') || jQuery(e.target).is('[type="text"]') ) ){ clearTimeout(typingTimer); typingTimer = setTimeout(function(){ executeChange(e, element) }, doneTypingInterval); }else{ executeChange(e, element); } }); var executeChange = function(e, element){ e.stopImmediatePropagation(); if(jQuery(e.target).is('[type="search"]') && jQuery(e.target).hasClass('search_icons')){ control.searchIcons( jQuery(e.target) ); } var el = e.target; /*if( jQuery(el).is('input') && jQuery(el).parent('.selectize-input').length > 0 ){ var el_correct = jQuery(el).closest('.element-wrapper').find('select'); el = el_correct; }*/ control.updateField.call(control, e, jQuery( el ).closest('.element-field').data( 'field' ), el ); if(jQuery(e.target).is('[type="range"]')){ element.closest( 'label' ).find( '.value input' ).prop( "value", jQuery(e.target).attr('value') ); } } this.container.on( 'keydown', 'input, select', function( e ) { clearTimeout(typingTimer); }); }, searchIcons: function( target ){ var icons_wrapper = target.parent().find('.icons-wrapper'); var val = target.val(); var selected = icons_wrapper.children("[id*='"+val+"']"); icons_wrapper.children( '.icon' ).not(selected).css('display', 'none'); selected.css('display', 'inline-block'); if( val == '' ) icons_wrapper.children( '.icon' ).css('display', 'inline-block'); }, /** * Open the media modal. */ activeTabs: function(){ var $actived = this.container.find('.tab_sections .active'); var actived_id = $actived.data('tab'); var control = this; control.container.find('#tab-'+actived_id).css({display:'block'}).addClass('active'); control.container.find('.tab_sections a').on('click', function(){ var $actived = jQuery(this); var actived_id = $actived.data('tab'); control.container.find('.tab_sections a').removeClass('active'); $actived.addClass('active'); control.container.find('.tab_section.active').removeClass('active').css({display:'none'}); control.container.find('#tab-'+actived_id).css({display:'block'}).addClass('active'); }); }, openFrame: function( event ) { 'use strict'; if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { return; } if ( this.$thisButton.closest( '.element-field' ).hasClass( 'element-field-cropped_image' ) ) { this.initCropperFrame(); } else { this.initFrame(); } this.frame.open(); }, initFrame: function() { 'use strict'; var libMediaType = this.getMimeType(); if ( typeof this.frame != 'undefined' ) { this.frame.close(); } if( ! _.isUndefined(wp.media.view.MediaFrame.CodelessPost) ) this.frame = new wp.media.view.MediaFrame.CodelessPost({ multiple:false, }); else{ this.frame = wp.media({ multiple:false }); this.frame.on( 'select', this.onSelect, this ); } // When a file is selected, run a callback. this.frame.on( 'insert', this.onSelect, this ); }, /** * Create a media modal select frame, and store it so the instance can be reused when needed. * This is mostly a copy/paste of Core api.CroppedImageControl in /wp-admin/js/customize-control.js */ initCropperFrame: function() { 'use strict'; // We get the field id from which this was called var currentFieldId = this.$thisButton.siblings( 'input.hidden-field' ).attr( 'data-field' ), attrs = [ 'width', 'height', 'flex_width', 'flex_height' ], // A list of attributes to look for libMediaType = this.getMimeType(); // Make sure we got it if ( 'string' === typeof currentFieldId && '' !== currentFieldId ) { // Make fields is defined and only do the hack for cropped_image if ( 'object' === typeof this.codelessElementMap[ currentFieldId ] && 'cropped_image' === this.codelessElementMap[ currentFieldId ].type ) { //Iterate over the list of attributes attrs.forEach( function( el, index ) { // If the attribute exists in the field if ( 'undefined' !== typeof this.codelessElementMap[ currentFieldId ][ el ] ) { // Set the attribute in the main object this.params[ el ] = this.codelessElementMap[ currentFieldId ][ el ]; } }.bind( this ) ); } } this.frame = wp.media({ button: { text: 'Select and Crop', close: false }, states: [ new wp.media.controller.Library({ library: wp.media.query({ type: libMediaType }), multiple: false, date: false, suggestedWidth: this.params.width, suggestedHeight: this.params.height }), new wp.media.controller.CustomizeImageCropper({ imgSelectOptions: this.calculateImageSelectOptions, control: this }) ] }); this.frame.on( 'select', this.onSelectForCrop, this ); this.frame.on( 'cropped', this.onCropped, this ); this.frame.on( 'skippedcrop', this.onSkippedCrop, this ); }, onSelect: function() { 'use strict'; var sel = this.frame.state().get( 'selection' ).first(); var attachment = !_.isUndefined(sel) ? sel.toJSON() : ''; var mime = attachment.mime, regex = /^image\/(?:jpe?g|png|url|gif|x-icon)$/i; if (mime.match(regex)) { this.setImageInRepeaterField( attachment ); } else { this.setOembed( attachment ); } }, /** * After an image is selected in the media modal, switch to the cropper * state if the image isn't the right size. */ onSelectForCrop: function() { 'use strict'; var attachment = this.frame.state().get( 'selection' ).first().toJSON(); if ( this.params.width === attachment.width && this.params.height === attachment.height && ! this.params.flex_width && ! this.params.flex_height ) { this.setImageInRepeaterField( attachment ); } else { this.frame.setState( 'cropper' ); } }, /** * After the image has been cropped, apply the cropped image data to the setting. * * @param {object} croppedImage Cropped attachment data. */ onCropped: function( croppedImage ) { 'use strict'; this.setImageInRepeaterField( croppedImage ); }, /** * Returns a set of options, computed from the attached image data and * control-specific data, to be fed to the imgAreaSelect plugin in * wp.media.view.Cropper. * * @param {wp.media.model.Attachment} attachment * @param {wp.media.controller.Cropper} controller * @returns {Object} Options */ calculateImageSelectOptions: function( attachment, controller ) { 'use strict'; var control = controller.get( 'control' ), flexWidth = !! parseInt( control.params.flex_width, 10 ), flexHeight = !! parseInt( control.params.flex_height, 10 ), realWidth = attachment.get( 'width' ), realHeight = attachment.get( 'height' ), xInit = parseInt( control.params.width, 10 ), yInit = parseInt( control.params.height, 10 ), ratio = xInit / yInit, xImg = realWidth, yImg = realHeight, x1, y1, imgSelectOptions; controller.set( 'canSkipCrop', ! control.mustBeCropped( flexWidth, flexHeight, xInit, yInit, realWidth, realHeight ) ); if ( xImg / yImg > ratio ) { yInit = yImg; xInit = yInit * ratio; } else { xInit = xImg; yInit = xInit / ratio; } x1 = ( xImg - xInit ) / 2; y1 = ( yImg - yInit ) / 2; imgSelectOptions = { handles: true, keys: true, instance: true, persistent: true, imageWidth: realWidth, imageHeight: realHeight, x1: x1, y1: y1, x2: xInit + x1, y2: yInit + y1 }; if ( false === flexHeight && false === flexWidth ) { imgSelectOptions.aspectRatio = xInit + ':' + yInit; } if ( false === flexHeight ) { imgSelectOptions.maxHeight = yInit; } if ( false === flexWidth ) { imgSelectOptions.maxWidth = xInit; } return imgSelectOptions; }, /** * Return whether the image must be cropped, based on required dimensions. * * @param {bool} flexW * @param {bool} flexH * @param {int} dstW * @param {int} dstH * @param {int} imgW * @param {int} imgH * @return {bool} */ mustBeCropped: function( flexW, flexH, dstW, dstH, imgW, imgH ) { 'use strict'; if ( true === flexW && true === flexH ) { return false; } if ( true === flexW && dstH === imgH ) { return false; } if ( true === flexH && dstW === imgW ) { return false; } if ( dstW === imgW && dstH === imgH ) { return false; } if ( imgW <= dstW ) { return false; } return true; }, /** * If cropping was skipped, apply the image data directly to the setting. */ onSkippedCrop: function() { 'use strict'; var attachment = this.frame.state().get( 'selection' ).first().toJSON(); this.setImageInRepeaterField( attachment ); }, /** * Updates the setting and re-renders the control UI. * * @param {object} attachment */ setImageInRepeaterField: function( attachment ) { 'use strict'; var that = this; var $targetDiv = this.$thisButton.closest( '.element-field-image,.element-field-cropped_image' ); $targetDiv.find( '.kirki-image-attachment' ).html( '' ); $targetDiv.find( '.kirki-image-attachment' ).addClass("added_image"); $targetDiv.find( '.hidden-field' ).val( attachment.id ); this.$thisButton.text( this.$thisButton.data( 'alt-label' ) ); $targetDiv.find( '.remove-button' ).show(); //This will activate the save button $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); this.frame.close(); }, setOembed: function( attachment ) { 'use strict'; var that = this; var $targetDiv = this.$thisButton.closest( '.element-field-image,.element-field-cropped_image' ); $targetDiv.find( '.kirki-image-attachment' ).html( '
'+attachment.title+'
' ); $targetDiv.find( '.kirki-image-attachment' ).addClass("added_image"); $targetDiv.find( '.hidden-field' ).val( attachment.id ); this.$thisButton.text( this.$thisButton.data( 'alt-label' ) ); $targetDiv.find( '.remove-button' ).show(); //This will activate the save button $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); this.frame.close(); }, /** * Updates the setting and re-renders the control UI. * * @param {object} attachment */ setFileInRepeaterField: function( attachment ) { 'use strict'; var $targetDiv = this.$thisButton.closest( '.element-field-upload' ); $targetDiv.find( '.kirki-file-attachment' ).html( ' ' + attachment.filename + '' ).hide().slideDown( 'slow' ); $targetDiv.find( '.hidden-field' ).val( attachment.id ); this.$thisButton.text( this.$thisButton.data( 'alt-label' ) ); $targetDiv.find( '.upload-button' ).show(); $targetDiv.find( '.remove-button' ).show(); //This will activate the save button $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); this.frame.close(); }, getMimeType: function() { 'use strict'; // We get the field id from which this was called var currentFieldId = this.$thisButton.siblings( 'input.hidden-field' ).attr( 'data-field' ), attrs = [ 'mime_type' ]; // A list of attributes to look for // Make sure we got it if ( 'string' === typeof currentFieldId && '' !== currentFieldId ) { // Make fields is defined and only do the hack for cropped_image if ( 'object' === typeof this.codelessElementMap[ currentFieldId ] && 'upload' === this.codelessElementMap[ currentFieldId ].type ) { // If the attribute exists in the field if ( 'undefined' !== typeof this.codelessElementMap[ currentFieldId ].mime_type ) { // Set the attribute in the main object return this.codelessElementMap[ currentFieldId ].mime_type; } } } return 'image'; }, removeImage: function( event ) { 'use strict'; var $targetDiv, $uploadButton; if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { return; } $targetDiv = this.$thisButton.closest( '.element-field-image,.element-field-cropped_image,.element-field-upload' ); $uploadButton = $targetDiv.find( '.upload-button' ); var $a = $targetDiv.find( '.kirki-image-attachment' ); $a.show().html( $a.data( 'placeholder' ) ); $a.removeClass('added_image'); $targetDiv.find( '.hidden-field' ).val( '' ); $uploadButton.text( $uploadButton.data( 'label' ) ); this.$thisButton.hide(); $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); }, removeFile: function( event ) { 'use strict'; var $targetDiv, $uploadButton; if ( wp.customize.utils.isKeydownButNotEnterEvent( event ) ) { return; } $targetDiv = this.$thisButton.closest( '.element-field-upload' ); $uploadButton = $targetDiv.find( '.upload-button' ); $targetDiv.find( '.kirki-file-attachment' ).slideUp( 'fast', function() { jQuery( this ).show().html( jQuery( this ).data( 'placeholder' ) ); }); $targetDiv.find( '.hidden-field' ).val( '' ); $uploadButton.text( $uploadButton.data( 'label' ) ); this.$thisButton.hide(); $targetDiv.find( 'input, textarea, select' ).trigger( 'change' ); }, /** * Get the current value of the setting * * @return Object */ getValue: function() { 'use strict'; return this.element_values; }, /** * Set a new value for the setting * * @param newValue Object * @param refresh If we want to refresh the previewer or not */ setValue: function( newValue, refresh, filtering, fieldId, field_type, selector, css_property, subKey ) { 'use strict'; this.element_values[fieldId] = newValue; this.setting.previewer.send('cl_element_updated', [this.element_id, fieldId, field_type, newValue, selector, css_property, this.cl_required[fieldId], subKey] ); }, /** * Add a new row to repeater settings based on the structure. * * @param data (Optional) Object of field => value pairs (undefined if you want to get the default values) */ addElements: function( data, first ) { 'use strict'; var control = this, //template = control.elementTemplate(), // The template for the new row (defined on Kirki_Customize_Repeater_Control::render_content() ). settingValue = this.getValue(), // Get the current setting value. newRowSetting = [], // Saves the new setting data. templateData, // Data to pass to the template newRow, temporaryHtml = '', u, i; var reMap = { 'color': 'kirki-color', 'switch': 'kirki-switch', 'select': 'kirki-select', 'slider': 'kirki-slider', 'inline_select': 'kirki-select', 'text' : 'cltext', 'image' : 'kirki-image', 'multicheck': 'kirki-multicheck' } // The control structure is going to define the new fields // We need to clone control.params.fields. Assigning it // ould result in a reference assignment. templateData = jQuery.extend( true, {}, control.codelessElementMap ); _.each( templateData, function( value, key ){ var type = value['type'], newType = _.isUndefined( reMap[type] ) ? type : reMap[type]; value['value'] = !_.isUndefined( data[key] ) ? data[key] : value['default']; control.element_values[key] = value['value']; value['id'] = key; if( type == 'inline_text' || type == 'select_icon' || ( !_.isUndefined( value['show'] ) && !value['show'] ) ) return true; if( !_.isUndefined( value['alpha'] ) ){ value['choices'] = {}; value['choices'] = {alpha: true}; } if( type == 'slider' ){ value['inputAttrs'] = 'value="'+value['value']+'" min="'+value['choices']['min']+'" max="'+value['choices']['max']+'" step="'+value['choices']['step']+'"'; } var template = control.elementTemplate( newType ); console.log(newType); template = template( value ); if( type != 'show_tabs' && type != 'tab_start' && type != 'tab_end' && type != 'group_start' && type != 'group_end' ){ var tooltip_trigger = '', tooltip_content = '', tooltip_wrapper = ''; if( !_.isUndefined( value.tooltip ) ){ tooltip_trigger = ''; tooltip_content = ''; tooltip_wrapper = '
' + trigger + content + '
'; } template = '
' + tooltip_wrapper + template + '
'; } temporaryHtml += template; } ); control.elementsFieldsContainer.html( temporaryHtml ); // But if we have passed data, we'll use the data values instead /*if ( data ) { for ( i in data ) { if ( data.hasOwnProperty( i ) && templateData.hasOwnProperty( i ) ) { templateData[ i ]['default'] = data[ i ]; } } } // Append the template content template = template( templateData ); control.elementsFieldsContainer.html(template); for ( u in templateData ) { if ( templateData.hasOwnProperty( u ) ) { settingValue[u] = templateData[ u ]['default']; } } this.setValue( settingValue, false ); return newRow;*/ }, /** * Update a single field inside a row. * Triggered when a field has changed * * @param e Event Object */ updateField: function( e, fieldId, element ) { 'use strict'; var type, subKey, currentSettings, control = this, currentValue; if ( ! this.codelessElementMap[ fieldId ] ) { return; } type = this.codelessElementMap[ fieldId].type; currentSettings = this.getValue(); element = jQuery( element ); if ( undefined === typeof currentSettings[ fieldId ] ) { return; } if ( 'checkbox' === type || 'switch' === type ) { currentValue = element.is( ':checked' ) ? 1 : 0; }else if('image' === type) { var final_img = {}; var sel = (!_.isUndefined(this.frame) ? this.frame.state().get( 'selection' ).first() : ''); if( !_.isUndefined(sel) && !_.isEmpty(sel) ){ sel = sel.toJSON(); _.each(sel, function(value, key){ final_img[key] = encodeURIComponent(value); }); } currentValue = final_img ; }else if('css_tool' === type){ var name = element.data('name'); if(!_.isObject(currentValue) ) currentValue = {}; if ( false === control.kirkiValidateCSSValue( element.val() ) && element.val() != '' ) { element.addClass('invalid'); return; }else{ element.removeClass('invalid'); currentValue = element.val(); if(element.val() == '' && !_.isUndefined(currentValue[name])) delete currentValue[ name ]; subKey = name; } } else if('multicheck' == type) { var value = {}, i = 0, control = this; jQuery.each( control.codelessElementMap[ fieldId].choices, function( key, subValue ) { if ( control.container.find( 'input[value="' + key + '"]' ).is( ':checked' ) ) { value[ i ] = key; i++; } }); currentValue = value; } else if('select' == type || type == 'inline_select'){ var value = element.val(); var multiple = parseInt( element.data( 'multiple' ) ); if ( multiple > 1 ) { value = _.extend( {}, element.val() ); } currentValue = value; } else { // Update the settings currentValue = element.val(); } console.log(currentValue); this.setValue( currentValue, true, false, fieldId, type, '', '', subKey ); this.checkDependecies(fieldId, currentValue); }, checkDependecies: function(fieldId, value){ var operators = { '==': function(a, b){ return a==b}, '!=': function(a, b){ return a!=b} } var control = this; if(!_.isUndefined(this.cl_required[fieldId]) && this.cl_required[fieldId].length ){ _.each(this.cl_required[fieldId], function(opt, index){ if(operators[opt['operator']](opt['value'], value ) ){ control.container.find('.id-'+opt['setting']).removeClass('show_on_required'); }else{ control.container.find('.id-'+opt['setting']).addClass('show_on_required'); } }); } }, /** * Init the color picker on color fields * Called after AddRow * */ initColorPicker: function() { 'use strict'; var control = this, colorPicker = control.container.find( '.kirki-color-control' ); jQuery.each(colorPicker, function(){ var colorPicker = jQuery(this); var options = {}; var fieldId = colorPicker.closest('.element-field').data( 'field' ); // We check if the color palette parameter is defined. if ( 'undefined' !== typeof fieldId && 'undefined' !== typeof control.codelessElementMap[ fieldId ] && 'undefined' !== typeof control.codelessElementMap[ fieldId ].palettes && 'object' === typeof control.codelessElementMap[ fieldId ].palettes ) { options.palettes = control.codelessElementMap[ fieldId ].palettes; } options.width = 259; options.palettes = codelessPalettes; // When the color picker value is changed we update the value of the field options.change = function( event, ui ) { var currentPicker = jQuery( event.target ), selector = '', css_property = ''; if('undefined' !== typeof control.codelessElementMap[ fieldId ].selector) selector = control.codelessElementMap[ fieldId ].selector; if('undefined' !== typeof control.codelessElementMap[ fieldId ].css_property) css_property = control.codelessElementMap[ fieldId ].css_property; control.setValue( ui.color.toString(), true, false, fieldId, 'color', selector, css_property ); }; // Init the color picker if ( 0 !== colorPicker.length ) { colorPicker.wpColorPicker( options ); } }); }, /** * Init the dropdown-pages field with selectize * Called after AddRow * * @param {object} theNewRow the row that was added to the repeater * @param {object} data the data for the row if we're initializing a pre-existing row * */ initSelect: function( data ) { 'use strict'; var control = this, dropdown = control.container.find( 'select' ), $select, dataField, multiple, selectWooOptions = {}; if ( 0 === dropdown.length ) { return; } dataField = dropdown.data( 'field' ); multiple = jQuery( dropdown ).data( 'multiple' ); if ( 'undefined' !== multiple && jQuery.isNumeric( multiple ) ) { multiple = parseInt( multiple, 10 ); if ( 1 < multiple ) { selectWooOptions.maximumSelectionLength = multiple; } } $select = jQuery( dropdown ).selectWoo( selectWooOptions ).val( dropdown.val() ); this.selects.push( $select ); }, updateSilent: function(element){ jQuery.each(this.selects[0], function(key, value){ if(jQuery(value).closest('.element-field').data('field') == element.id){ jQuery( value ).selectWoo().val( element.value ).trigger( 'change' ); } }); }, kirkiValidateCSSValue: function( value ) { var validUnits = ['rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax'], numericValue, unit; // 0 is always a valid value, and we can't check calc() values effectively. if ( '0' === value || ( 0 <= value.indexOf( 'calc(' ) && 0 <= value.indexOf( ')' ) ) ) { return true; } // Get the numeric value. numericValue = parseFloat( value ); // Get the unit unit = value.replace( numericValue, '' ); // Check the validity of the numeric value and units. if ( isNaN( numericValue ) || -1 === jQuery.inArray( unit, validUnits ) ) { return false; } return true; } });