(function($){ /** * Helper class for dealing with live previews. * * @class FLBuilderPreview * @since 1.3.3 * @param {Object} config */ FLBuilderPreview = function( config ) { // Set the preview ID. this.id = new Date().getTime(); // Set the type. this.type = config.type; // Save the current state. this._saveState(); // Initialize the preview. if ( config.layout ) { FLBuilder._renderLayout( config.layout, function() { this._init(); if ( config.callback ) { config.callback(); } }.bind( this ) ); } else { this._init(); } }; /** * Stores all the fonts and weights of all font fields. * This is used to render the stylesheet with Google Fonts. * * @since 1.6.3 * @access private * @property {Array} _fontsList */ FLBuilderPreview._fontsList = {}; /** * Returns a formatted selector string for a preview. * * @since 2.1 * @method getFormattedSelector * @param {String} selector A CSS selector string. * @return {String} */ FLBuilderPreview.getFormattedSelector = function( prefix, selector ) { var formatted = '', parts = selector.split( ',' ), i = 0; for ( ; i < parts.length; i++ ) { if ( parts[ i ].indexOf( '{node}' ) > -1 ) { formatted += parts[ i ].replace( '{node}', prefix ); } else if ( parts[ i ].indexOf( '{node_id}' ) > -1 ) { formatted += parts[ i ].replace( /{node_id}/g, this.nodeId ); } else { formatted += prefix + ' ' + parts[ i ]; } if ( i != parts.length - 1 ) { formatted += ', '; } } return formatted; }; /** * Prototype for new instances. * * @since 1.3.3 * @property {Object} prototype */ FLBuilderPreview.prototype = { /** * A unique ID for this preview. * * @since 1.3.3 * @property {String} id */ id : '', /** * The type of node that we are previewing. * * @since 1.3.3 * @property {String} type */ type : '', /** * The ID of node that we are previewing. * * @since 1.3.3 * @property {String} nodeId */ nodeId : null, /** * An object with data for each CSS class * in the preview. * * @since 1.3.3 * @property {Object} classes */ classes : {}, /** * An object with references to each element * in the preview. * * @since 1.3.3 * @property {Object} elements */ elements : {}, /** * An object that contains data for the current * state of a layout before changes are made. * * @since 1.3.3 * @property {Object} state */ state : null, /** * Node settings saved when the preview was initalized. * * @since 1.7 * @access private * @property {Object} _savedSettings */ _savedSettings : null, /** * An instance of FLStyleSheet for the current preview. * * @since 1.3.3 * @access private * @property {FLStyleSheet} _styleSheet */ _styleSheet : null, /** * An instance of FLStyleSheet for the large device preview. * * @since 2.6 * @access private * @property {FLStyleSheet} _styleSheetLarge */ _styleSheetLarge : null, /** * An instance of FLStyleSheet for the medium device preview. * * @since 1.9 * @access private * @property {FLStyleSheet} _styleSheetMedium */ _styleSheetMedium : null, /** * An instance of FLStyleSheet for the responsive device preview. * * @since 1.9 * @access private * @property {FLStyleSheet} _styleSheet */ _styleSheetResponsive : null, /** * A timeout object for delaying the current preview refresh. * * @since 1.3.3 * @access private * @property {Object} _timeout */ _timeout : null, /** * A timeout object for delaying when we show the loading * graphic for refresh previews. * * @since 1.10 * @access private * @property {Object} _loaderTimeout */ _loaderTimeout : null, /** * Stores the last classname for a classname preview. * * @since 1.3.3 * @access private * @property {String} _lastClassName */ _lastClassName : null, /** * A reference to the AJAX object for a preview refresh. * * @since 1.3.3 * @access private * @property {Object} _xhr */ _xhr : null, /** * Initializes a builder preview. * * @since 1.3.3 * @access private * @method _init */ _init: function() { // Node Id this.nodeId = $('.fl-builder-settings', window.parent.document).data('node'); // Save settings this._saveSettings(); // Elements and Class Names this._initElementsAndClasses(); // Create the preview stylesheets this._createSheets(); // Responsive previews this._initResponsivePreviews(); // Default field previews this._initDefaultFieldPreviews(); // Init switch(this.type) { case 'row': this._initRow(); break; case 'col': this._initColumn(); break; case 'module': this._initModule(); break; } FLBuilder.triggerHook( 'preview-init', this ); }, /** * Saves the current settings to be checked to see if * anything has changed when a preview is canceled. * * @since 1.7 * @access private * @method _saveSettings */ _saveSettings: function() { var form = $('.fl-builder-settings-lightbox .fl-builder-settings', window.parent.document); this._savedSettings = FLBuilder._getSettingsForChangedCheck( this.nodeId, form ); }, /** * Checks to see if the settings have changed. * * @since 1.7 * @access private * @method _settingsHaveChanged * @return bool */ _settingsHaveChanged: function() { var form = $('.fl-builder-settings-lightbox .fl-builder-settings', window.parent.document), settings = FLBuilder._getSettings( form ); return JSON.stringify( this._savedSettings ) != JSON.stringify( settings ); }, /** * Initializes the classname and element references * for this preview. * * @since 1.3.3 * @access private * @method _initElementsAndClasses */ _initElementsAndClasses: function() { var contentClass; // Content Class if(this.type == 'row') { contentClass = '.fl-row-content-wrap'; } else { contentClass = '.fl-' + this.type + '-content'; } // Class Names $.extend(this.classes, { settings : '.fl-builder-' + this.type + '-settings', settingsHeader : '.fl-builder-' + this.type + '-settings .fl-lightbox-header', node : FLBuilder._contentClass + ' .fl-node-' + this.nodeId, content : FLBuilder._contentClass + ' .fl-node-' + this.nodeId + ' > ' + contentClass }); // Elements $.extend(this.elements, { settings : $(this.classes.settings, window.parent.document), settingsHeader : $(this.classes.settingsHeader, window.parent.document), node : $(this.classes.node), content : $(this.classes.content) }); }, /** * Creates the stylesheets for default, medium * and responsive previews. * * @since 1.9 * @method _createSheets */ _createSheets: function() { this._destroySheets(); if ( ! this._styleSheet ) { this._styleSheet = new FLStyleSheet( { id : 'fl-builder-preview', className : 'fl-builder-preview-style' } ); } if ( ! this._styleSheetLarge) { this._styleSheetLarge = new FLStyleSheet( { id : 'fl-builder-preview-large', className : 'fl-builder-preview-style' } ); this._styleSheetLarge.disable(); } if ( ! this._styleSheetMedium ) { this._styleSheetMedium = new FLStyleSheet( { id : 'fl-builder-preview-medium', className : 'fl-builder-preview-style' } ); this._styleSheetMedium.disable(); } if ( ! this._styleSheetResponsive ) { this._styleSheetResponsive = new FLStyleSheet( { id : 'fl-builder-preview-responsive', className : 'fl-builder-preview-style' } ); this._styleSheetResponsive.disable(); } }, /** * Destroys all preview sheets. * * @since 1.9 * @method _destroySheets */ _destroySheets: function() { if ( this._styleSheet ) { this._styleSheet.destroy(); this._styleSheet = null; } if ( this._styleSheetLarge ) { this._styleSheetLarge.destroy(); this._styleSheetLarge = null; } if ( this._styleSheetMedium ) { this._styleSheetMedium.destroy(); this._styleSheetMedium = null; } if ( this._styleSheetResponsive ) { this._styleSheetResponsive.destroy(); this._styleSheetResponsive = null; } $( '.fl-builder-preview-style' ).remove(); }, /** * Disables preview styles for the current * responsive editing mode. * * @since 2.2 * @method _disableStyles */ _disableStyles: function() { var mode = FLBuilderResponsiveEditing._mode, config = FLBuilderConfig.global, node = this.elements.node; if ( 'responsive' === mode ) { FLBuilderSimulateMediaQuery.disableStyles( config.responsive_breakpoint ); this._styleSheetResponsive.disable(); } else if ( 'large' === mode ) { FLBuilderSimulateMediaQuery.disableStyles( config.large_breakpoint ); this._styleSheetLarge.disable(); } else if ( 'medium' === mode ) { FLBuilderSimulateMediaQuery.disableStyles( config.medium_breakpoint ); this._styleSheetMedium.disable(); } else { node.removeClass( function( i, className ) { return ( className.match( /fl-node-[^\s]*/g ) || [] ).join( ' ' ); } ); } }, /** * Enables preview styles for the current * responsive editing mode. * * @since 2.2 * @method _enableStyles */ _enableStyles: function() { var mode = FLBuilderResponsiveEditing._mode, node = this.elements.node; if ( 'responsive' === mode ) { FLBuilderSimulateMediaQuery.enableStyles(); this._styleSheetResponsive.enable(); } else if ( 'medium' === mode ) { FLBuilderSimulateMediaQuery.enableStyles(); this._styleSheetMedium.enable(); } else if ( 'large' === mode ) { FLBuilderSimulateMediaQuery.enableStyles(); this._styleSheetLarge.enable(); } else { node.addClass( 'fl-node-' + node.data( 'node' ) ); } }, /** * Attempt to find the default value for a CSS property. * * @since 2.2 * @method _getDefaultValue * @param {String} selector * @param {String} property * @return {String} */ _getDefaultValue: function( selector, property ) { var value = '', element = $( selector ), node = element.closest( '[data-node]' ), ignore = [ 'line-height', 'font-weight' ]; if ( 'width' === property ) { value = 'auto'; } else if ( -1 === $.inArray( property, ignore ) && node.length ) { this._disableStyles(); value = element.css( property ); this._enableStyles(); } return value; }, /** * Updates a CSS rule for this preview. * * @since 1.3.3 * @method updateCSSRule * @param {String} selector The CSS selector to update. * @param {String} property The CSS property to update. * @param {String} value The CSS value to update. * @param {String|Boolean} responsive If this preview is responsive or not. */ updateCSSRule: function( selector, property, value, responsive ) { var mode = FLBuilderResponsiveEditing._mode, sheetKey = ''; // Get the default value if needed. if ( '' === value || 'null' === value ) { value = this._getDefaultValue( selector, property ); } // Update the rule. if ( responsive ) { if ( 'string' === typeof responsive ) { sheetKey = this.toUpperCaseWords( responsive ); } else { sheetKey = 'default' === mode ? '' : this.toUpperCaseWords( mode ); } this[ '_styleSheet' + sheetKey ].updateRule( selector, property, value ); } else { this._styleSheet.updateRule( selector, property, value ); } }, /** * Runs a delay with a callback. * * @since 1.3.3 * @method delay * @param {Number} length How long to wait before running the callback. * @param {Function} callback A function to call when the delay is complete. */ delay: function(length, callback) { this._cancelDelay(); this._timeout = setTimeout(callback, length); }, /** * Cancels a preview refresh delay. * * @since 1.3.3 * @access private * @method _cancelDelay */ _cancelDelay: function() { if(this._timeout !== null) { clearTimeout(this._timeout); } }, /** * Converts a hex value to an array of RGB values. * * @since 1.3.3 * @method hexToRgb * @param {String} hex * @return {Array} */ hexToRgb: function(hex) { var bigInt = parseInt(hex, 16), r = (bigInt >> 16) & 255, g = (bigInt >> 8) & 255, b = bigInt & 255; return [r, g, b]; }, /** * Returns a hex or rgb formatted value. * * @since 2.0.3 * @method hexOrRgb * @param {String} value * @return {String} */ hexOrRgb: function( value ) { if ( value.indexOf( 'rgb' ) < 0 && value.indexOf( '#' ) < 0 ) { value = '#' + value; } return value; }, /** * Parses a float or returns 0 if we don't have a number. * * @since 1.3.3 * @method parseFloat * @param {Number} value * @return {Number} */ parseFloat: function(value) { return isNaN(parseFloat(value)) ? 0 : parseFloat(value); }, /* Responsive Previews ----------------------------------------------------------*/ /** * Initializes logic for responsive previews. * * @since 1.9 * @method _initResponsivePreviews */ _initResponsivePreviews: function() { var namespace = '.preview-' + this.id; FLBuilder.addHook( 'responsive-editing-switched' + namespace, $.proxy( this._responsiveEditingSwitched, this ) ); FLBuilder.addHook( 'responsive-editing-before-preview-fields' + namespace, $.proxy( this._responsiveEditingPreviewFields, this ) ); }, /** * Destroys responsive preview events. * * @since 1.9 * @method _destroyResponsivePreviews */ _destroyResponsivePreviews: function() { var namespace = '.preview-' + this.id; FLBuilder.removeHook( 'responsive-editing-switched' + namespace ); FLBuilder.removeHook( 'responsive-editing-before-preview-fields' + namespace ); }, /** * Initializes logic for responsive previews. * * @since 1.9 * @method _responsiveEditingSwitched */ _responsiveEditingSwitched: function( e, mode ) { if ( 'default' == mode ) { this._styleSheetLarge.disable(); this._styleSheetMedium.disable(); this._styleSheetResponsive.disable(); } else if ( 'large' == mode ) { this._styleSheetLarge.enable(); this._styleSheetMedium.disable(); this._styleSheetResponsive.disable(); } else if ( 'medium' == mode ) { this._styleSheetLarge.enable(); this._styleSheetMedium.enable(); this._styleSheetResponsive.disable(); } else if ( 'responsive' == mode ) { this._styleSheetLarge.enable(); this._styleSheetMedium.enable(); this._styleSheetResponsive.enable(); } }, /** * Logic that needs to run before field previews are triggered * after responsive editing mode switches. * * @since 2.2 * @method _responsiveEditingPreviewFields */ _responsiveEditingPreviewFields: function( e, mode ) { if ( 'large' === mode || 'medium' === mode ) { if ( 'col' === this.type && this.elements.node[0].style.width ) { size = parseFloat( this.elements.node[0].style.width ); this.elements.size.val( size ); } } }, /** * Deprecated. Use updateCSSRule instead. * * @since 1.9 */ updateResponsiveCSSRule: function( selector, property, value ) { this.updateCSSRule( selector, property, value, true ); }, /* States ----------------------------------------------------------*/ /** * Saves the current state of a layout. * * @since 1.3.3 * @access private * @method _saveState */ _saveState: function() { var post = FLBuilderConfig.postId, css = $('link[href*="/cache/' + post + '"]').attr('href'), js = $('script[src*="/cache/' + post + '"]').attr('src'), html = $(FLBuilder._contentClass).html(); this.state = { css : css, js : js, html : html }; }, /** * Runs a preview refresh for the current settings lightbox. * * @since 1.3.3 * @method preview */ preview: function() { var form = $('.fl-builder-settings-lightbox .fl-builder-settings', window.parent.document), nodeId = form.attr('data-node'), settings = FLBuilder._getSettings(form); // Show the node as loading. FLBuilder._showNodeLoading( nodeId ); // Abort an existing preview request. this._cancelPreview(); settings = FLBuilder._inputVarsCheck( settings ); if ( 'error' === settings ) { return 0; } // Make a new preview request. this._xhr = FLBuilder.ajax({ action : 'render_layout', node_id : nodeId, node_preview : settings }, $.proxy(this._renderPreview, this)); }, /** * Runs a preview refresh with a delay. * * @since 1.3.3 * @method delayPreview */ delayPreview: function(e) { var heading = typeof e == 'undefined' ? [] : $(e.target).closest('tr').find('th'), widgetHeading = $('.fl-builder-widget-settings .fl-builder-settings-title', window.parent.document), lightboxHeading = $('.fl-builder-settings .fl-lightbox-header', window.parent.document), loaderSrc = FLBuilderLayoutConfig.paths.pluginUrl + 'img/ajax-loader-small.svg', loader = $(''); this.delay(1000, $.proxy(this.preview, this)); this._loaderTimeout = setTimeout( function() { $('.fl-builder-preview-loader', window.parent.document).remove(); if(heading.length > 0) { heading.append(loader); } else if(widgetHeading.length > 0) { widgetHeading.append(loader); } else if(lightboxHeading.length > 0) { lightboxHeading.append(loader); } }, 1500 ); }, /** * Cancels a preview refresh. * * @since 1.3.3 * @access private * @method _cancelPreview */ _cancelPreview: function() { if(this._xhr) { this._xhr.abort(); this._xhr = null; } }, /** * Renders the response of a preview refresh. * * @since 1.3.3 * @access private * @method _renderPreview * @param {String} response The JSON encoded response. */ _renderPreview: function(response) { this._xhr = null; FLBuilder._renderLayout(response, $.proxy(this._renderPreviewComplete, this)); }, /** * Fires when a preview refresh has finished rendering. * * @since 1.3.3 * @access private * @method _renderPreviewComplete */ _renderPreviewComplete: function() { // Refresh the preview styles. this._createSheets(); // Refresh the elements. this._initElementsAndClasses(); // Refresh preview config for element references. this._initDefaultFieldPreviews(); // Clear the loader timeout. if(this._loaderTimeout !== null) { clearTimeout(this._loaderTimeout); } /** * Remove the loading graphic * 2.6.0.2 added 500ms delay to fix #2234 */ setTimeout( function() { $('.fl-builder-preview-loader', window.parent.document).remove(); }, 500 ); // Fire the preview rendered event. $( FLBuilder._contentClass ).trigger( 'fl-builder.preview-rendered' ); }, /** * Reverts a preview to the state that was saved * before the preview was initialized. * * @since 1.3.3 * @method revert */ revert: function() { var nodeId = this.nodeId; if ( ! this._settingsHaveChanged() ) { this.clear(); return; } if ( 'col' === this.type ) { nodeId = this.elements.node.closest( '.fl-col-group' ).data( 'node' ); } FLBuilder._updateNode( nodeId, function() { this.clear(); }.bind( this ) ); }, /** * Cancels a preview refresh. * * @since 1.3.3 * @method clear */ cancel: function() { this._cancelDelay(); this._cancelPreview(); }, /** * Cancels a preview refresh and removes * any stylesheet changes. * * @since 1.3.3 * @method clear */ clear: function() { // Canel any preview delays or requests. this.cancel(); // Destroy the preview stylesheet. this._destroySheets(); // Destroy responsive editing previews. this._destroyResponsivePreviews(); }, /* Node Text Color Settings ----------------------------------------------------------*/ /** * Initializes node text color previews. * * @since 1.3.3 * @access private * @method _initNodeTextColor */ _initNodeTextColor: function() { // Elements $.extend(this.elements, { textColor : $(this.classes.settings + ' input[name=text_color]', window.parent.document), linkColor : $(this.classes.settings + ' input[name=link_color]', window.parent.document), hoverColor : $(this.classes.settings + ' input[name=hover_color]', window.parent.document), headingColor : $(this.classes.settings + ' input[name=heading_color]', window.parent.document) }); // Events this.elements.textColor.on('change', $.proxy(this._textColorChange, this)); this.elements.linkColor.on('change', $.proxy(this._textColorChange, this)); this.elements.hoverColor.on('change', $.proxy(this._textColorChange, this)); this.elements.headingColor.on('change', $.proxy(this._textColorChange, this)); }, /** * Fires when the text color field for a node * is changed. * * @since 1.3.3 * @access private * @method _textColorChange * @param {Object} e An event object. */ _textColorChange: function(e) { var textColor = this.elements.textColor.val(), linkColor = this.elements.linkColor.val(), hoverColor = this.elements.hoverColor.val(), headingColor = this.elements.headingColor.val(); linkColor = linkColor === '' ? textColor : linkColor; hoverColor = hoverColor === '' ? textColor : hoverColor; headingColor = headingColor === '' ? textColor : headingColor; if ( textColor && textColor.indexOf( 'rgb' ) < 0 ) { textColor = '#' + textColor; } if ( linkColor && linkColor.indexOf( 'rgb' ) < 0 ) { linkColor = '#' + linkColor; } if ( hoverColor && hoverColor.indexOf( 'rgb' ) < 0 ) { hoverColor = '#' + hoverColor; } if ( headingColor && headingColor.indexOf( 'rgb' ) < 0 ) { headingColor = '#' + headingColor; } this.delay(50, $.proxy(function(){ // Update Text color. if(textColor === '') { this.updateCSSRule(this.classes.node, 'color', ''); } else { this.updateCSSRule(this.classes.node, 'color', textColor); } // Update Link Color if ( linkColor === '' ) { this.updateCSSRule(this.classes.node + ' a', 'color', ''); } else { this.updateCSSRule(this.classes.node + ' a', 'color', linkColor); } // Hover Color if(hoverColor === '') { this.updateCSSRule(this.classes.node + ' a:hover', 'color', ''); } else { this.updateCSSRule(this.classes.node + ' a:hover', 'color', hoverColor); } // Heading Color if(headingColor === '') { this.updateCSSRule(this.classes.node + ' h1', 'color', ''); this.updateCSSRule(this.classes.node + ' h2', 'color', ''); this.updateCSSRule(this.classes.node + ' h3', 'color', ''); this.updateCSSRule(this.classes.node + ' h4', 'color', ''); this.updateCSSRule(this.classes.node + ' h5', 'color', ''); this.updateCSSRule(this.classes.node + ' h6', 'color', ''); this.updateCSSRule(this.classes.node + ' h1 a', 'color', ''); this.updateCSSRule(this.classes.node + ' h2 a', 'color', ''); this.updateCSSRule(this.classes.node + ' h3 a', 'color', ''); this.updateCSSRule(this.classes.node + ' h4 a', 'color', ''); this.updateCSSRule(this.classes.node + ' h5 a', 'color', ''); this.updateCSSRule(this.classes.node + ' h6 a', 'color', ''); } else { this.updateCSSRule(this.classes.node + ' h1', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h2', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h3', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h4', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h5', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h6', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h1 a', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h2 a', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h3 a', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h4 a', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h5 a', 'color', headingColor); this.updateCSSRule(this.classes.node + ' h6 a', 'color', headingColor); } }, this)); }, /* Node Bg Settings ----------------------------------------------------------*/ /** * Initializes node background previews. * * @since 1.3.3 * @access private * @method _initNodeBg */ _initNodeBg: function() { // Elements $.extend(this.elements, { bgType : $(this.classes.settings + ' select[name=bg_type]', window.parent.document), bgColor : $(this.classes.settings + ' input[name=bg_color]', window.parent.document), bgColorPicker : $(this.classes.settings + ' .fl-picker-bg_color', window.parent.document), bgGradientType : $(this.classes.settings + ' select.fl-gradient-picker-type-select', window.parent.document), bgVideoSource : $(this.classes.settings + ' select[name=bg_video_source]', window.parent.document), bgVideo : $(this.classes.settings + ' input[name=bg_video]', window.parent.document), bgVideoServiceUrl : $(this.classes.settings + ' input[name=bg_video_service_url]', window.parent.document), bgVideoFallbackSrc : $(this.classes.settings + ' select[name=bg_video_fallback_src]', window.parent.document), bgSlideshowSource : $(this.classes.settings + ' select[name=ss_source]', window.parent.document), bgSlideshowPhotos : $(this.classes.settings + ' input[name=ss_photos]', window.parent.document), bgSlideshowFeedUrl : $(this.classes.settings + ' input[name=ss_feed_url]', window.parent.document), bgSlideshowSpeed : $(this.classes.settings + ' input[name=ss_speed]', window.parent.document), bgSlideshowTrans : $(this.classes.settings + ' select[name=ss_transition]', window.parent.document), bgSlideshowTransSpeed : $(this.classes.settings + ' input[name=ss_transitionDuration]', window.parent.document), bgParallaxImageSrc : $(this.classes.settings + ' select[name=bg_parallax_image_src]', window.parent.document), bgOverlayType : $(this.classes.settings + ' select[name=bg_overlay_type]', window.parent.document), bgOverlayColor : $(this.classes.settings + ' input[name=bg_overlay_color]', window.parent.document), bgOverlayGradient : $(this.classes.settings + ' #fl-field-bg_overlay_gradient select', window.parent.document), }); // Events this.elements.bgType.on( 'change', $.proxy(this._bgTypeChange, this)); this.elements.bgColor.on( 'change', $.proxy(this._bgColorChange, this)); this.elements.bgVideoServiceUrl.on( 'change', $.proxy(this._bgVideoChange, this)); this.elements.bgSlideshowSource.on( 'change', $.proxy(this._bgSlideshowChange, this)); this.elements.bgSlideshowPhotos.on( 'change', $.proxy(this._bgSlideshowChange, this)); this.elements.bgSlideshowFeedUrl.on( 'keyup', $.proxy(this._bgSlideshowChange, this)); this.elements.bgSlideshowSpeed.on( 'keyup', $.proxy(this._bgSlideshowChange, this)); this.elements.bgSlideshowTrans.on( 'change', $.proxy(this._bgSlideshowChange, this)); this.elements.bgSlideshowTransSpeed.on( 'keyup', $.proxy(this._bgSlideshowChange, this)); this.elements.bgParallaxImageSrc.on( 'change', $.proxy(this._bgParallaxChange, this)); this.elements.bgOverlayType.on( 'change', $.proxy(this._bgOverlayChange, this)); this.elements.bgOverlayColor.on( 'change', $.proxy(this._bgOverlayChange, this)); }, /** * Fires when the background type field of * a node changes. * * @since 1.3.3 * @access private * @method _bgTypeChange * @param {Object} e An event object. */ _bgTypeChange: function(e) { var val = this.elements.bgType.val(), mode = FLBuilderResponsiveEditing._mode; // Clear bg styles first. this.elements.node.removeClass('fl-row-bg-video'); this.elements.node.removeClass('fl-row-bg-slideshow'); this.elements.node.removeClass('fl-row-bg-parallax'); this.elements.node.find('.fl-bg-video').remove(); this.elements.node.find('.fl-bg-slideshow').remove(); this.elements.content.css('background-image', ''); this.updateCSSRule(this.classes.content, 'background-color', 'transparent'); this.updateCSSRule(this.classes.content, 'background-image', 'none'); this.updateCSSRule(this.classes.content, 'background-image', 'none', 'medium'); this.updateCSSRule(this.classes.content, 'background-image', 'none', 'responsive'); // None if(val == 'none') { this._bgOverlayClear(); } // Color else if(val == 'color') { this.elements.bgColor.trigger('change'); this._bgOverlayClear(); } // Gradient else if(val == 'gradient') { this.elements.bgGradientType.trigger('change'); this._bgOverlayClear(); } // Photo else if(val == 'photo') { this.elements.bgColor.trigger('change'); this.elements.settings.find( '[data-device="' + mode + '"] select[name*="bg_"]' ).trigger( 'change' ); } // Video else if(val == 'video') { this.elements.bgColor.trigger('change'); this._bgVideoChange(); } // Slideshow else if(val == 'slideshow') { this.elements.bgColor.trigger('change'); this._bgSlideshowChange(); } // Parallax else if(val == 'parallax') { this.elements.bgColor.trigger('change'); this.elements.bgParallaxImageSrc.trigger('change'); } }, /** * Fires when the background color field of * a node changes. * * @since 1.3.3 * @access private * @method _bgColorChange * @param {Object} e An event object. */ _bgColorChange: function(e) { var rgb, alpha, value; if(this.elements.bgColor.val() === '') { this.updateCSSRule(this.classes.content, 'background-color', 'transparent'); } else { value = this.hexOrRgb( this.elements.bgColor.val() ); this.delay(100, $.proxy(function(){ this.updateCSSRule(this.classes.content, 'background-color', value); }, this)); } }, /** * Fires when the background video field of * a node changes. * * @since 1.9.2 * @access private * @method _bgVideoChange * @param {Object} e An event object. */ _bgVideoChange: function(e) { var eles = this.elements, source = eles.bgVideoSource.val(), video = eles.bgVideo.val(), videoUrl = eles.bgVideoServiceUrl.val(), youtubePlayer = 'https://www.youtube.com/iframe_api', vimeoPlayer = 'https://player.vimeo.com/api/player.js', scriptTag = $( '