1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628 |
- (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 = '',
- pattern = /,(?![^()]*\))/,
- parts = selector.split( pattern ),
- 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();
- this._bindEvents()
- },
- _bindEvents() {
- // 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':
- case 'form':
- 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';
- }
- let formSelector = '.fl-builder-settings-lightbox:visible form.fl-builder-settings'
- // Class Names
- $.extend(this.classes, {
- settings : formSelector,
- settingsHeader : formSelector + ' .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);
- }
- if(this._loaderTimeout !== null) {
- clearTimeout(this._loaderTimeout);
- }
- },
- /**
- * 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 = $('<img class="fl-builder-preview-loader" src="' + loaderSrc + '" />');
- 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 = $( '<script>' );
- // Only load the required API script library
- if(source == 'video_service' && videoUrl != '') {
- if (/^(?:(?:(?:https?:)?\/\/)?(?:www.)?(?:youtu(?:be.com|.be))\/(?:watch\?v\=|v\/|embed\/)?([\w\-]+))/i.test(videoUrl)
- && $( 'script[src*="youtube.com"' ).length < 1) {
- scriptTag.attr('src', youtubePlayer);
- }
- else if(/^(http\:\/\/|https\:\/\/)?(www\.)?(vimeo\.com\/)([0-9]+)$/.test(videoUrl)
- && $( 'script[src*="vimeo.com"' ).length < 1) {
- scriptTag.attr('src', vimeoPlayer);
- }
- scriptTag
- .attr('type', 'text/javascript')
- .appendTo('head');
- this.delay(500, $.proxy(this.preview, this));
- }
- else if(video != '') {
- this.preview();
- }
- },
- /**
- * Fires when the background slideshow field of
- * a node changes.
- *
- * @since 1.3.3
- * @access private
- * @method _bgSlideshowChange
- * @param {Object} e An event object.
- */
- _bgSlideshowChange: function(e)
- {
- var eles = this.elements,
- source = eles.bgSlideshowSource.val(),
- photos = eles.bgSlideshowPhotos.val(),
- feed = eles.bgSlideshowFeedUrl.val(),
- speed = eles.bgSlideshowSpeed.val(),
- transSpeed = eles.bgSlideshowTransSpeed.val();
- if(source == 'wordpress' && photos === '') {
- return;
- }
- else if(source == 'smugmug' && feed === '') {
- return;
- }
- else if(isNaN(parseInt(speed))) {
- return;
- }
- else if(isNaN(parseInt(transSpeed))) {
- return;
- }
- this.delay(500, $.proxy(this.preview, this));
- },
- /**
- * Fires when the background parallax field of
- * a node changes.
- *
- * @since 1.3.3
- * @access private
- * @method _bgParallaxChange
- * @param {Object} e An event object.
- */
- _bgParallaxChange: function(e)
- {
- if(this.elements.bgParallaxImageSrc.val()) {
- this.updateCSSRule(this.classes.content, {
- 'background-image' : 'url(' + this.elements.bgParallaxImageSrc.val() + ')',
- 'background-repeat' : 'no-repeat',
- 'background-position' : 'center center',
- 'background-attachment' : 'fixed',
- 'background-size' : 'cover'
- });
- }
- },
- /**
- * Fires when the background overlay field of
- * a node changes.
- *
- * @since 1.3.3
- * @access private
- * @method _bgOverlayChange
- * @param {Object} e An event object.
- */
- _bgOverlayChange: function(e)
- {
- var type = this.elements.bgOverlayType.val(),
- color = this.elements.bgOverlayColor.val(),
- rgb, alpha, value;
- if ( 'color' === type ) {
- if ( color === '' ) {
- this.elements.node.removeClass('fl-row-bg-overlay');
- this.elements.node.removeClass('fl-col-bg-overlay');
- this.updateCSSRule(this.classes.content + '::after', 'background-color', 'transparent');
- } else {
- value = this.hexOrRgb( this.elements.bgOverlayColor.val() );
- this.delay(100, $.proxy(function(){
- this._bgOverlayAddClasses();
- this.updateCSSRule( this.classes.content + '::after', 'background-color', value );
- }, this));
- }
- this.updateCSSRule(this.classes.content + '::after', 'background-image', 'none');
- } else if ( 'gradient' === type ) {
- this._bgOverlayAddClasses();
- this.updateCSSRule(this.classes.content + '::after', 'background-color', 'transparent');
- this.elements.bgOverlayGradient.trigger( 'change' );
- } else {
- this.elements.node.removeClass('fl-row-bg-overlay');
- this.elements.node.removeClass('fl-col-bg-overlay');
- this.updateCSSRule(this.classes.content + '::after', 'background-color', 'transparent');
- this.updateCSSRule(this.classes.content + '::after', 'background-image', 'none');
- }
- },
- /**
- * Adds the necessary classes for background overlays.
- *
- * @since 2.2
- * @access private
- * @method _bgOverlayAddClasses
- */
- _bgOverlayAddClasses: function() {
- if ( this.elements.node.hasClass( 'fl-col' ) ) {
- this.elements.node.addClass( 'fl-col-bg-overlay' );
- } else {
- this.elements.node.addClass( 'fl-row-bg-overlay' );
- }
- },
- /**
- * Fires when a background overlay color is cleared.
- *
- * @since 1.3.3
- * @access private
- * @method _bgOverlayClear
- * @param {Object} e An event object.
- */
- _bgOverlayClear: function(e)
- {
- this.elements.bgOverlayColor.prev('.fl-color-picker-clear').trigger('click');
- this.elements.bgOverlayType.val( 'color' ).trigger( 'change' );
- },
- /* Node Class Name Settings
- ----------------------------------------------------------*/
- /**
- * Initializes node classname previews.
- *
- * @since 1.3.3
- * @access private
- * @method _initNodeClassName
- */
- _initNodeClassName: function()
- {
- // Elements
- $.extend(this.elements, {
- className : $(this.classes.settings + ' input[name=class]', window.parent.document)
- });
- // Events
- this.elements.className.on('keyup', $.proxy(this._classNameChange, this));
- this._lastClassName = this.elements.className.val();
- },
- /**
- * Fires when the classname of a node changes.
- *
- * @since 1.3.3
- * @access private
- * @method _classNameChange
- * @param {Object} e An event object.
- */
- _classNameChange: function(e)
- {
- var className = this.elements.className.val();
- if(this._lastClassName !== null) {
- this.elements.node.removeClass(this._lastClassName);
- }
- this.elements.node.addClass(className);
- this._lastClassName = className;
- },
- /* Node Spacing Settings
- ----------------------------------------------------------*/
- /**
- * Initializes node responsive dimension previews for things
- * like margins, padding and borders.
- *
- * @since 1.9
- * @access private
- * @method _initNodeDimensions
- */
- _initNodeDimensions: function( property )
- {
- var elements = {},
- dimensions = [ 'Top', 'Bottom', 'Left', 'Right' ],
- devices = [ '', 'Large', 'Medium', 'Responsive' ],
- settingsClass = this.classes.settings,
- elementKey = '',
- inputName = '',
- i = null,
- k = null;
- for ( i = 0; i < dimensions.length; i++ ) {
- for ( k = 0; k < devices.length; k++ ) {
- elementKey = property + dimensions[ i ] + devices[ k ];
- inputName = property + '_' + dimensions[ i ].toLowerCase();
- if ( '' != devices[ k ] ) {
- inputName += '_' + devices[ k ].toLowerCase();
- }
- elements[ elementKey ] = $( settingsClass + ' input[name=' + inputName + ']', window.parent.document );
- }
- }
- $.extend( this.elements, elements );
- },
- /* Row Settings
- ----------------------------------------------------------*/
- /**
- * Initializes a row preview.
- *
- * @since 1.3.3
- * @access private
- * @method _initRow
- */
- _initRow: function()
- {
- // Elements
- $.extend(this.elements, {
- width : $(this.classes.settings + ' select[name=width]', window.parent.document),
- contentWidth : $(this.classes.settings + ' select[name=content_width]', window.parent.document),
- maxContentWidth : $(this.classes.settings + ' input[name=max_content_width]', window.parent.document),
- maxContentWidthUnit : $(this.classes.settings + ' select[name=max_content_width_unit]', window.parent.document),
- height : $(this.classes.settings + ' select[name=full_height]', window.parent.document),
- minHeight : $(this.classes.settings + ' input[name=min_height]', window.parent.document),
- align : $(this.classes.settings + ' select[name=content_alignment]', window.parent.document)
- });
- // Events
- this.elements.width.on( 'change', $.proxy(this._rowWidthChange, this));
- this.elements.contentWidth.on( 'change', $.proxy(this._rowContentWidthChange, this));
- this.elements.maxContentWidth.on( 'input', $.proxy(this._rowMaxContentWidthChange, this));
- this.elements.maxContentWidthUnit.on( 'change', $.proxy(this._rowMaxContentWidthChange, this));
- this.elements.height.on( 'change', $.proxy(this._rowHeightChange, this));
- this.elements.align.on( 'change', $.proxy(this._rowHeightChange, this));
- // Common Elements
- this._initNodeTextColor();
- this._initNodeBg();
- this._initNodeClassName();
- this._initNodeDimensions( 'border' );
- this._initNodeDimensions( 'margin' );
- this._initNodeDimensions( 'padding' );
- },
- /**
- * Fires when the width field of a row changes.
- *
- * @since 1.3.3
- * @access private
- * @method _rowWidthChange
- * @param {Object} e An event object.
- */
- _rowWidthChange: function(e)
- {
- var settings = FLBuilderConfig.global,
- row = this.elements.node,
- content = this.elements.content.find('.fl-row-content'),
- maxWidth = this.elements.maxContentWidth.val(),
- maxWidthUnit = this.elements.maxContentWidthUnit.val();
- row.css( 'max-width', 'none' );
- content.css( 'max-width', 'none' );
- if(this.elements.width.val() == 'full') {
- row.removeClass('fl-row-fixed-width');
- row.addClass('fl-row-full-width');
- }
- else {
- row.removeClass('fl-row-full-width');
- row.addClass('fl-row-fixed-width');
- }
- this._rowMaxContentWidthChange();
- },
- /**
- * Fires when the content width field of a row changes.
- *
- * @since 1.3.3
- * @access private
- * @method _rowContentWidthChange
- * @param {Object} e An event object.
- */
- _rowContentWidthChange: function(e)
- {
- var settings = FLBuilderConfig.global,
- row = this.elements.node,
- content = this.elements.content.find('.fl-row-content'),
- maxWidth = this.elements.maxContentWidth.val(),
- maxWidthUnit = this.elements.maxContentWidthUnit.val();
- row.css( 'max-width', 'none' );
- content.css( 'max-width', 'none' );
- if(this.elements.contentWidth.val() == 'full') {
- content.removeClass('fl-row-fixed-width');
- content.addClass('fl-row-full-width');
- }
- else {
- content.removeClass('fl-row-full-width');
- content.addClass('fl-row-fixed-width');
- this._rowMaxContentWidthChange();
- }
- },
- /**
- * Fires when the content width field of a row changes.
- *
- * @since 1.3.3
- * @access private
- * @method _rowContentWidthChange
- * @param {Object} e An event object.
- */
- _rowMaxContentWidthChange: function(e)
- {
- var settings = FLBuilderConfig.global,
- row = this.elements.node,
- content = this.elements.content.find('.fl-row-content'),
- width = this.elements.maxContentWidth.val(),
- unit = this.elements.maxContentWidthUnit.val();
- if ( '' == width ) {
- width = settings.row_width + settings.row_width_unit;
- } else {
- width += unit;
- }
- if ( 'fixed' === this.elements.width.val() ) {
- row.css( 'max-width', width );
- }
- content.css( 'max-width', width );
- },
- /**
- * Fires when the height field of a row changes.
- *
- * @since 1.6.3
- * @access private
- * @method _rowHeightChange
- * @param {Object} e An event object.
- */
- _rowHeightChange: function(e)
- {
- var row = this.elements.node;
- row.removeClass('fl-row-align-top');
- row.removeClass('fl-row-align-center');
- row.removeClass('fl-row-align-bottom');
- row.removeClass('fl-row-default-height');
- row.removeClass('fl-row-full-height');
- row.removeClass('fl-row-custom-height');
- if(this.elements.height.val() == 'full') {
- row.addClass('fl-row-full-height');
- row.addClass('fl-row-align-' + this.elements.align.val());
- this.elements.minHeight.val( '' ).trigger( 'input' );
- } else if(this.elements.height.val() == 'custom') {
- row.addClass('fl-row-custom-height');
- row.addClass('fl-row-align-' + this.elements.align.val());
- this.elements.minHeight.trigger( 'input' );
- } else {
- row.addClass('fl-row-default-height');
- row.addClass('fl-row-align-' + this.elements.align.val());
- this.elements.minHeight.val( '' ).trigger( 'input' );
- }
- },
- /* Columns Settings
- ----------------------------------------------------------*/
- /**
- * Initializes a column preview.
- *
- * @since 1.3.3
- * @access private
- * @method _initRow
- */
- _initColumn: function()
- {
- // Elements
- $.extend(this.elements, {
- size : $(this.classes.settings + ' input[name=size]', window.parent.document),
- sizeLarge : $(this.classes.settings + ' input[name=size_large]', window.parent.document),
- sizeMedium : $(this.classes.settings + ' input[name=size_medium]', window.parent.document),
- sizeResponsive : $(this.classes.settings + ' input[name=size_responsive]', window.parent.document),
- columnHeight : $(this.classes.settings + ' select[name=equal_height]', window.parent.document),
- columnAlign : $(this.classes.settings + ' select[name=content_alignment]', window.parent.document),
- responsiveOrder : $(this.classes.settings + ' select[name=responsive_order]', window.parent.document)
- });
- // Events
- this.elements.size.on( 'input', $.proxy( this._colSizeChange, this ) );
- this.elements.sizeLarge.on( 'input', $.proxy( this._colSizeChange, this ) );
- this.elements.sizeMedium.on( 'input', $.proxy( this._colSizeChange, this ) );
- this.elements.sizeResponsive.on( 'input', $.proxy( this._colSizeChange, this ) );
- this.elements.columnHeight.on( 'change', $.proxy( this._colHeightChange, this ) );
- this.elements.columnAlign.on( 'change', $.proxy( this._colHeightChange, this ) );
- this.elements.responsiveOrder.on( 'change', $.proxy( this._colResponsiveOrder, this ) );
- // Common Elements
- this._initNodeTextColor();
- this._initNodeBg();
- this._initNodeClassName();
- this._initNodeDimensions( 'border' );
- this._initNodeDimensions( 'margin' );
- this._initNodeDimensions( 'padding' );
- },
- /**
- * Fires when the size field of a column changes.
- *
- * @since 1.3.3
- * @access private
- * @method _colSizeChange
- */
- _colSizeChange: function( e )
- {
- var input = $( e.target ),
- minWidth = 8,
- maxWidth = 100 - minWidth,
- size = parseFloat( input.val() ),
- group = this.elements.node.closest( '.fl-col-group' ),
- prev = this.elements.node.prev('.fl-col'),
- next = this.elements.node.next('.fl-col'),
- sibling = next.length === 0 ? prev : next,
- siblings = this.elements.node.siblings('.fl-col'),
- siblingsWidth = 0,
- mode = FLBuilderResponsiveEditing._mode;
- // Don't resize if we only have one column.
- if(siblings.length === 0) {
- return;
- }
- // Find the fallback size if we don't have a number.
- if ( isNaN( size ) ) {
- if ( 'large' === mode ) {
- size = this.elements.size.val();
- } else if ( 'medium' === mode ) {
- if ( this.elements.sizeLarge.val() ) {
- size = this.elements.sizeLarge.val();
- } else {
- size = this.elements.size.val();
- }
- } else if ( 'responsive' === mode ) {
- if ( this.elements.sizeMedium.val() ) {
- size = this.elements.sizeMedium.val();
- } else if ( this.elements.sizeLarge.val() ) {
- size = this.elements.sizeLarge.val();
- } else {
- size = 'auto';
- }
- }
- if ( 'auto' !== size && isNaN( size ) ) {
- size = minWidth;
- }
- }
- // Default mode logic to keep columns from stacking because of resize.
- if ( 'default' === mode ) {
- // Adjust sizes based on other columns.
- siblings.each(function() {
- if($(this).data('node') == sibling.data('node')) {
- return;
- }
- maxWidth -= parseFloat($(this)[0].style.width);
- siblingsWidth += parseFloat($(this)[0].style.width);
- });
- // Make sure the new width isn't too small.
- if(size < minWidth) {
- size = minWidth;
- }
- // Make sure the new width isn't too big.
- if(size > maxWidth) {
- size = maxWidth;
- }
- // Update the width.
- this.elements.node.css('width', size + '%');
- sibling.css('width', (100 - siblingsWidth - size) + '%');
- } else {
- // Don't allow resizing past 100%.
- if ( size > 100 ) {
- size = 100;
- input.val( 100 );
- }
- // Update the width for responsive sizes.
- this.updateCSSRule( this.classes.node, {
- 'max-width': ( 'auto' === size ? 100 : size ) + '% !important',
- 'width': ( 'auto' === size ? size : size + '%' ) + ' !important',
- }, undefined, true );
- // Float the column only if we have a responsive size.
- if ( 'responsive' === mode ) {
- if ( input.val() ) {
- this.updateCSSRule( this.classes.node, 'float', ( FLBuilderConfig.isRtl ? 'right' : 'left' ), true );
- this.updateCSSRule( this.classes.node, 'clear', 'none', true );
- } else {
- this.updateCSSRule( this.classes.node, 'float', 'none', true );
- this.updateCSSRule( this.classes.node, 'clear', 'both', true );
- }
- if ( input.val() || this._colsHaveCustomResponsiveWidth( siblings ) ) {
- group.addClass( 'fl-col-group-custom-width' );
- } else {
- group.removeClass( 'fl-col-group-custom-width' );
- }
- }
- }
- },
- /**
- * Checks to see if any columns in a group have
- * custom responsive widths.
- *
- * @since 2.2
- * @access private
- * @method _colsHaveCustomResponsiveWidth
- * @return {Boolean}
- */
- _colsHaveCustomResponsiveWidth: function( cols )
- {
- var settings = FLBuilderSettingsConfig.nodes,
- hasWidth = false;
- cols.each( function() {
- var id = $( this ).data( 'node' );
- if ( settings[ id ] && settings[ id ].size_responsive ) {
- hasWidth = true;
- }
- } );
- return hasWidth;
- },
- /**
- * Fires when the equal height field of a column changes.
- *
- * @since 1.6.3
- * @access private
- * @method _colHeightChange
- */
- _colHeightChange: function()
- {
- var parent = this.elements.node.parent('.fl-col-group');
- parent.removeClass('fl-col-group-align-top');
- parent.removeClass('fl-col-group-align-center');
- parent.removeClass('fl-col-group-align-bottom');
- if(this.elements.columnHeight.val() == 'yes') {
- parent.addClass('fl-col-group-equal-height');
- parent.addClass('fl-col-group-align-' + this.elements.columnAlign.val());
- }
- else {
- parent.removeClass('fl-col-group-equal-height');
- }
- },
- /**
- * Fires when the responsive order field of a column changes.
- *
- * @since 1.8
- * @access private
- * @method _colResponsiveOrder
- */
- _colResponsiveOrder: function()
- {
- var parent = this.elements.node.parent('.fl-col-group'),
- enabledOn = this.elements.responsiveOrder.val().split(',');
- if ( enabledOn.includes( 'medium' ) ) {
- parent.addClass('fl-col-group-medium-reversed');
- } else {
- parent.removeClass('fl-col-group-medium-reversed');
- }
- if ( enabledOn.includes( 'mobile' ) ) {
- parent.addClass('fl-col-group-responsive-reversed');
- } else {
- parent.removeClass('fl-col-group-responsive-reversed');
- }
- },
- /* Module Settings
- ----------------------------------------------------------*/
- /**
- * Initializes a module preview.
- *
- * @since 1.3.3
- * @access private
- * @method _initModule
- */
- _initModule: function()
- {
- this._initNodeClassName();
- this._initNodeDimensions( 'margin' );
- },
- /* Default Field Previews
- ----------------------------------------------------------*/
- /**
- * Initializes the default preview logic for each
- * field in a settings form.
- *
- * @since 1.3.3
- * @access private
- * @method _initDefaultFieldPreviews
- * @param {Object} fields
- */
- _initDefaultFieldPreviews: function( fields )
- {
- var fields = ! FLBuilder.isUndefined(fields) ? fields : this.elements.settings.find('.fl-field'),
- field = null,
- fieldType = null,
- preview = null,
- i = 0;
- if ( FLBuilderConfig.safemode ) {
- return false;
- }
- for( ; i < fields.length; i++) {
- field = fields.eq(i);
- fieldType = field.data( 'type' );
- preview = field.data('preview');
- if(preview.type == 'refresh') {
- this._initFieldRefreshPreview(field);
- }
- if(preview.type == 'text') {
- this._initFieldTextPreview(field);
- }
- if(preview.type == 'css') {
- this._initFieldCSSPreview(field);
- }
- if(preview.type == 'widget') {
- this._initFieldWidgetPreview(field);
- }
- if(preview.type == 'font') {
- this._initFieldFontPreview(field);
- }
- if(preview.type == 'attribute') {
- this._initFieldAttributePreview(field);
- }
- if(preview.type == 'animation') {
- this._initFieldAnimationPreview(preview, field);
- }
- if(preview.type == 'callback') {
- this._initFieldCallbackPreview( preview, field, fieldType, fields );
- }
- this._initFieldUnitSelect(field);
- }
- },
- /**
- * Setup callback type previews
- *
- * @since 2.2
- * @access private
- * @method _initFieldCallbackPreview
- * @param {Object} preview - the preview args from the field configuration
- * @param {Object} field - reference to the .fl-field DOM element
- * @return void
- */
- _initFieldCallbackPreview: function ( preview, field, fieldType, fields ) {
- var callback,
- callback_name = preview['callback'],
- form = $( '.fl-builder-settings:visible', window.parent.document ),
- nodeID = form.data('node'),
- node = $('.fl-builder-content .fl-node-' + nodeID );
- if ( 'undefined' !== typeof FLBuilderPreviewCallbacks[callback_name] ) {
- callback = FLBuilderPreviewCallbacks[callback_name];
- } else if ( 'undefined' !== typeof window[callback_name] ) {
- callback = window[callback_name];
- } else if ( 'undefined' !== typeof window.parent[callback_name] ) {
- callback = window.parent[callback_name];
- }
- if ( 'function' === typeof callback ) {
- var args = {
- field: field,
- fields: fields,
- type: fieldType,
- preview: preview,
- form: form,
- nodeID: nodeID,
- node: node,
- };
- // Grab input references
- switch( fieldType ) {
- case 'align':
- case 'button-group':
- case 'text':
- case 'multiple-photos':
- case 'video':
- case 'icon':
- case 'ordering':
- args.input = field.find('input:not(.fl-preview-ignore)');
- args.getValue = function() {
- return args.input.val();
- }
- break;
- case 'color':
- args.input = field.find('input.fl-color-picker-value');
- args.getValues = function() {
- var value = args.input.val(),
- values = {
- value: value,
- formattedValue: FLBuilderPreview.formatColor( value ),
- };
- }
- break;
- case 'textarea':
- case 'code':
- args.textarea = field.find('textarea');
- args.getValue = function() {
- return args.textarea.val();
- }
- break;
- case 'select':
- case 'photo-sizes':
- case 'post-type':
- args.select = field.find('select');
- args.getValue = function() {
- return args.select.val();
- }
- break;
- case 'photo':
- args.input = field.find('input[type=hidden]:not(.fl-preview-ignore)');
- args.sizeSelect = field.find('select');
- args.getValues = function() {
- return {
- value: args.input.val(),
- size: args.sizeSelect.val(),
- };
- }
- break;
- case 'unit':
- args.input = field.find('input[type=number]');
- args.unitSelect = field.find( '.fl-field-unit-select' );
- args.getValues = function() {
- var inputVal = args.input.val(),
- unitVal = args.unitSelect.val(),
- values = {
- value: inputVal,
- unit: unitVal,
- formattedValue: inputVal + unitVal
- };
- return values;
- }
- break;
- case 'dimension':
- args.inputs = field.find('input[type=number]');
- args.unitSelect = field.find( '.fl-field-unit-select' );
- args.getValues = function() {
- var values = {
- inputs: [],
- props: {},
- unit: args.unitSelect.val(),
- };
- args.inputs.each( function( i, input ) {
- var input = $( input ),
- val = input.val(),
- prop = input.data('unit');
- values.inputs.push( val );
- values.props[prop] = val;
- } );
- return values;
- }
- break;
- case 'animation':
- args.input = field.find('input:not(.fl-preview-ignore)');
- args.select = field.find('select');
- args.getValues = function() {
- return {
- delay: args.input.val(),
- style: args.select.val(),
- };
- }
- break;
- case 'link':
- args.input = field.find('.fl-link-field-input-wrap input:not(.fl-preview-ignore)');
- args.targetInput = field.find('input[name$=_target]');
- args.noFollowInput = field.find('input[name$=_nofollow]');
- args.getValues = function() {
- return {
- url: args.input.val(),
- target: args.targetInput.val(),
- noFollow: args.noFollowInput.val(),
- }
- }
- break;
- case 'shadow':
- args.colorInput = field.find('input.fl-color-picker-value');
- args.inputs = field.find('input[type=number]');
- args.getValues = function() {
- var values = {
- color: args.colorInput.val(),
- x: args.inputs[0].val(),
- y: args.inputs[1].val(),
- blur: args.inputs[2].val(),
- spread: args.inputs[3].val(),
- }
- }
- break;
- case 'gradient':
- // for event setup
- args.inputs = field.find('input:not(.fl-preview-ignore)');
- args.select = field.find('select');
- // callback helpers
- args.gradientInputs = {};
- args.gradientInputs.type = field.find('select[name$="[type]"]');
- args.gradientInputs.angle = field.find('input[name$="[angle]"]');
- args.gradientInputs.position = field.find('select[name$="[position]"]');
- args.gradientInputs.stops = [];
- field.find('.fl-gradient-picker-colors .fl-gradient-picker-color-row').each( function( i, row ) {
- row = $(row);
- args.gradientInputs.stops.push({
- color: row.find('.fl-gradient-picker-color input'),
- stop: row.find('.fl-gradient-picker-stop input'),
- });
- });
- args.getValues = function() {
- var values = {
- type: args.gradientInputs.type.val(),
- angle: args.gradientInputs.angle.val(),
- position: args.gradientInputs.position.val(),
- stops: [],
- };
- for( var i in args.gradientInputs.stops ) {
- var stop = args.gradientInputs.stops[i];
- values.stops[i] = {
- color: stop.color.val(),
- stop: stop.stop.val(),
- }
- }
- return values;
- }
- break;
- case 'shape-transform':
- args.inputs = field.find('input:not(.fl-preview-ignore)');
- args.getValues = function() {
- return {
- scaleXSign: args.inputs.eq(0).val(),
- scaleYSign: args.inputs.eq(1).val(),
- skewX: args.inputs.eq(2).val(),
- skewY: args.inputs.eq(3).val(),
- scaleX: args.inputs.eq(4).val(),
- rotate: args.inputs.eq(5).val(),
- scaleY: args.inputs.eq(6).val(), /* hidden field */
- }
- }
- break;
- default:
- args.input = field.find('input:not(.fl-preview-ignore)');
- args.getValue = function() {
- return args.input.val();
- }
- }
- // Grab reference to responsive toggle
- var toggle = field.find( '.fl-field-responsive-toggle');
- args.responsiveToggle = toggle.length ? toggle : false;
- callback = callback.bind( this, args );
- // Loop over gathered inputs and setup event listeners
- var props = {
- input: 'change keyup input',
- inputs: 'change keyup input',
- targetInput: 'change keyup input',
- noFollowInput: 'change keyup input',
- colorInput: 'change input',
- textarea: 'change keyup input',
- select: 'change',
- sizeSelect: 'change',
- unitSelect: 'change',
- };
- for( var i in props ) {
- if ( 'undefined' !== typeof args[i] ) {
- args[i].on( props[i], callback );
- }
- }
- }
- },
- /* Refresh Preview
- ----------------------------------------------------------*/
- /**
- * Initializes the refresh preview for a field.
- *
- * @since 1.3.3
- * @access private
- * @method _initFieldRefreshPreview
- * @param {Object} field The field to preview.
- */
- _initFieldRefreshPreview: function(field)
- {
- var fieldType = field.data('type'),
- preview = field.data('preview'),
- callback = $.proxy(this.delayPreview, this);
- switch(fieldType) {
- case 'align':
- field.find( 'input:not(.fl-preview-ignore)' ).on( 'change', callback );
- break;
- case 'text':
- field.find('input[type=text]:not(.fl-preview-ignore)').on('keyup', callback);
- break;
- case 'textarea':
- field.find('textarea:not(.fl-preview-ignore)').on('keyup', callback);
- break;
- case 'select':
- field.find('select:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'color':
- field.find('.fl-color-picker-value').on('change', callback);
- break;
- case 'photo':
- field.find('select:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'multiple-photos':
- field.find('input:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'photo-sizes':
- field.find('select:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'video':
- field.find('input:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'multiple-audios':
- field.find('input:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'icon':
- field.find('input:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'form':
- field.on( 'change', 'input:not(.fl-preview-ignore)', callback);
- break;
- case 'editor':
- this._addTextEditorCallback(field, preview);
- break;
- case 'code':
- field.find('textarea:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'post-type':
- field.find('select:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'suggest':
- field.find('.as-values').on('change', callback);
- field.find('select:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'unit':
- case 'dimension':
- field.find('input[type=number]:not(.fl-preview-ignore)').on('input', callback);
- break;
- case 'ordering':
- field.find('input[type=hidden]:not(.fl-preview-ignore)').on('change', callback);
- break;
- default:
- field.on('change', callback);
- }
- },
- /* Text Preview
- ----------------------------------------------------------*/
- /**
- * Initializes a text preview for a field.
- *
- * @since 1.3.3
- * @access private
- * @method _initFieldTextPreview
- * @param {Object} field The field to preview.
- */
- _initFieldTextPreview: function(field)
- {
- var fieldType = field.data('type'),
- preview = field.data('preview'),
- callback = $.proxy(this._previewText, this, preview);
- switch(fieldType) {
- case 'text':
- field.find('input[type=text]:not(.fl-preview-ignore)').on('keyup', callback);
- break;
- case 'unit':
- field.find('input[type=number]:not(.fl-preview-ignore)').on('keyup', callback);
- break;
- case 'textarea':
- field.find('textarea:not(.fl-preview-ignore)').on('keyup', callback);
- break;
- case 'code':
- field.find('textarea:not(.fl-preview-ignore)').on('change', callback);
- break;
- case 'editor':
- this._addTextEditorCallback(field, preview);
- break;
- }
- },
- /**
- * Runs a real time preview for text fields.
- *
- * @since 1.3.3
- * @access private
- * @method _previewText
- * @param {Object} preview A preview object.
- * @param {Object} e An event object.
- */
- _previewText: function(preview, e)
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- element = $( selector ),
- text = $('<div>' + $(e.target).val() + '</div>');
- if(element.length > 0) {
- text.find('script').remove();
- element.html(text.html());
- } else {
- this.delayPreview(e);
- }
- },
- /**
- * Runs a real time preview for text editor fields.
- *
- * @since 1.3.3
- * @access private
- * @method _previewText
- * @param {Object} preview A preview object.
- * @param {String} id The ID of the text editor.
- * @param {Object} e An event object.
- */
- _previewTextEditor: function(preview, id, e)
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- element = $( selector ),
- editor = typeof window.parent.tinyMCE != 'undefined' ? window.parent.tinyMCE.get(id) : null,
- textarea = $('#' + id, window.parent.document),
- text = '';
- if(element.length > 0) {
- if(editor && textarea.css('display') == 'none') {
- text = $('<div>' + editor.getContent() + '</div>');
- }
- else {
- if ( 'undefined' == typeof switchEditors || 'undefined' == typeof switchEditors.wpautop ) {
- text = $('<div>' + textarea.val() + '</div>');
- }
- else {
- text = $('<div>' + switchEditors.wpautop( textarea.val() ) + '</div>');
- }
- }
- text.find('script').remove();
- element.html(text.html());
- }
- },
- /**
- * Callback for text editor previews.
- *
- * @since 1.3.3
- * @access private
- * @method _previewText
- * @param {Object} field A field object.
- * @param {Object} preview A preview object.
- */
- _addTextEditorCallback: function(field, preview)
- {
- var id = field.find('textarea.wp-editor-area').attr('id'),
- callback = null;
- if(preview.type == 'refresh') {
- callback = $.proxy(this.delayPreview, this);
- }
- else if(preview.type == 'text') {
- callback = $.proxy(this._previewTextEditor, this, preview, id);
- }
- else {
- return;
- }
- $('#' + id, window.parent.document).on('keyup', callback);
- if(typeof window.parent.tinyMCE != 'undefined') {
- editor = window.parent.tinyMCE.get(id);
- editor.on('change', callback);
- editor.on('keyup', callback);
- }
- },
- /* Font Field Preview
- ----------------------------------------------------------*/
- /**
- * Initializes a font preview for a field.
- *
- * @since 1.3.3
- * @access private
- * @method _initFieldFontPreview
- * @param {Object} field The field to preview.
- */
- _initFieldFontPreview: function(field)
- {
- var fieldType = field.data('type'),
- preview = field.data('preview');
- // store field id
- preview.id = field.attr( 'id' );
- var callback = $.proxy(this._previewFont, this, preview);
- if( fieldType == 'font' ){
- field.find('.fl-font-field').on('change', 'select', callback);
- }
- },
- /**
- * Gets the selected font and weight, and make the necessary updates for live preview.
- *
- * @since 1.6.3
- * @access private
- * @see _getPreviewSelector
- * @see _buildFontStylesheet
- * @see updateCSSRule
- *
- * @method _previewFont
- * @param {Object} preview An object with data about the current field and css selector.
- * @param {[type]} e The current field.
- */
- _previewFont: function( preview, e ){
- var parent = $( e.delegateTarget ),
- font = parent.find( '.fl-font-field-font' ),
- selected = $( font ).find( ':selected' ),
- fontGroup = selected.parent().attr( 'label' ),
- weight = parent.find( '.fl-font-field-weight' ),
- uniqueID = preview.id + '-' + this.nodeId,
- selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- important = preview.important ? ' !important' : '',
- val = ''
- // If the selected font is a Google Font, build the font stylesheet
- if( fontGroup == 'Google' || fontGroup == 'Recently Used' ){
- this._buildFontStylesheet( uniqueID, font.val(), weight.val() );
- }
- val = font.val();
- // Some google fonts that end with numbers need to be wrapped in quotes.
- var checkNum = new RegExp('[0-9]');
- if( checkNum.test( font.val() ) ){
- val = '"' + font.val() + '"';
- }
- this.updateCSSRule( selector, 'font-family', 'Default' === font.val() ? '' : val + important );
- this.updateCSSRule( selector, 'font-weight', 'default' === weight.val() ? '' : weight.val() + important );
- },
- /**
- * Gets all fonts store insite FLBuilderPreview._fontsList and renders the respective
- * link tag with Google Fonts.
- *
- * @since 1.6.3
- * @access private
- *
- * @method _buildFontStylesheet
- * @param {String} id The field unique ID.
- * @param {String} font The selected font.
- * @param {String} weight The selected weight.
- */
- _buildFontStylesheet: function( id, font, weight ){
- var url = FLBuilderConfig.googleFontsUrl,
- href = '',
- fontObj = {},
- fontArray = {};
- // build the font family / weight object
- fontObj[ font ] = [ weight ];
- // adds to the list of fonts for this font setting
- FLBuilderPreview._fontsList[ id ] = fontObj;
- // iterate over the keys of the FLBuilderPreview._fontsList object
- Object.keys( FLBuilderPreview._fontsList ).forEach( function( fieldFont ) {
- var field = FLBuilderPreview._fontsList[ fieldFont ];
- // iterate over the font / weight object
- Object.keys( field ).forEach( function( key ) {
- // get the weights of this font
- var weights = field[ key ];
- fontArray[ key ] = fontArray[ key ] || [];
- // remove duplicates from the values array
- weights = weights.filter( function( weight ) {
- return fontArray[ key ].indexOf( weight ) < 0;
- });
- fontArray[ key ] = fontArray[ key ].concat( weights );
- });
- });
- $.each( fontArray, function( font, weight ){
- if ( 'Molle' === font ) {
- href += font + ':i|';
- } else {
- href += font + ':' + weight.join() + '|';
- }
- } );
- // remove last character and replace spaces with plus signs
- href = url + href.slice( 0, -1 ).replace( ' ', '+' );
- if( $( '#fl-builder-google-fonts-preview' ).length < 1 ){
- $( '<link>' )
- .attr( 'id', 'fl-builder-google-fonts-preview' )
- .attr( 'type', 'text/css' )
- .attr( 'rel', 'stylesheet' )
- .attr( 'href', href )
- .appendTo('head');
- } else{
- $( '#fl-builder-google-fonts-preview' ).attr( 'href', href );
- }
- },
- /* CSS Preview
- ----------------------------------------------------------*/
- /**
- * Initializes CSS previews for a node.
- *
- * @since 1.3.3
- * @since 1.6.1 Reworked to accept a preview.rules array.
- * @access private
- * @method _initFieldCSSPreview
- * @param {Object} field A field object.
- */
- _initFieldCSSPreview: function( field )
- {
- var preview = field.data( 'preview' ),
- i = null;
- if ( 'undefined' != typeof preview.rules ) {
- for ( i in preview.rules ) {
- this._initFieldCSSPreviewCallback( field, preview.rules[ i ] );
- }
- }
- else {
- this._initFieldCSSPreviewCallback( field, preview );
- }
- },
- /**
- * Initializes CSS preview callbacks for a field.
- *
- * @since 1.6.1
- * @access private
- * @method _initFieldCSSPreviewCallback
- * @param {Object} field A field object.
- * @param {Object} preview The preview data object.
- */
- _initFieldCSSPreviewCallback: function( field, preview )
- {
- switch ( field.data( 'type' ) ) {
- case 'align':
- case 'justify':
- case 'grid-auto-flow':
- field.find( 'input:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'object-fit':
- // Position Sub-field
- field.find( 'input:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewCSS, this, preview, field ) );
- // Fit Button Group
- const fit = field.find( 'input[type="hidden"]:not(.fl-preview-ignore)' )
- fit.on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- fit.on( 'change', $.proxy( this._previewFieldObjectFit, this, preview, field ) );
- break;
- case 'border':
- field.find( 'select:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewBorderCSS, this, preview, field ) );
- field.find( 'input[type=number]:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewBorderCSS, this, preview, field ) );
- field.find( 'input[type=hidden]:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewBorderCSS, this, preview, field ) );
- break;
- case 'color':
- field.find( '.fl-color-picker-value' ).on( 'change', $.proxy( this._previewColorCSS, this, preview, field ) );
- break;
- case 'dimension':
- field.find( 'input[type=number]:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewDimensionCSS, this, preview, field ) );
- break;
- case 'gradient':
- field.find( 'select:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewGradientCSS, this, preview, field ) );
- field.find( '.fl-gradient-picker-angle' ).on( 'input', $.proxy( this._previewGradientCSS, this, preview, field ) );
- field.find( '.fl-color-picker-value' ).on( 'change', $.proxy( this._previewGradientCSS, this, preview, field ) );
- field.find( '.fl-gradient-picker-stop' ).on( 'input', $.proxy( this._previewGradientCSS, this, preview, field ) );
- break;
- case 'photo':
- field.find( 'select:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'select':
- case 'aspect-ratio':
- case 'placement':
- field.find( 'select:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'shadow':
- field.find( 'input:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewShadowCSS, this, preview, field ) );
- field.find( '.fl-color-picker-value' ).on( 'change', $.proxy( this._previewShadowCSS, this, preview, field ) );
- break;
- case 'text':
- field.find( 'input[type=text]:not(.fl-preview-ignore)' ).on( 'keyup input change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'hidden':
- field.find( 'input[type=hidden]:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'typography':
- field.find( 'select:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewTypographyCSS, this, preview, field ) );
- field.find( 'input[type=number]:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewTypographyCSS, this, preview, field ) );
- field.find( 'input[type=hidden]:not(.fl-preview-ignore)' ).on( 'change', $.proxy( this._previewTypographyCSS, this, preview, field ) );
- break;
- case 'unit':
- field.find( 'input[type=number]:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'button-group':
- case 'grid-tracklist':
- case 'grid-area':
- field.find( 'input[type=hidden]:not(.fl-preview-ignore)').on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- case 'flex':
- case 'size':
- field.find( 'input[type=number]:not(.fl-preview-ignore)' ).on( 'input', $.proxy( this._previewCSS, this, preview, field ) );
- field.find( 'input[type=hidden]:not(.fl-preview-ignore)').on( 'change', $.proxy( this._previewCSS, this, preview, field ) );
- break;
- }
- },
- /**
- * Updates the CSS rule for a preview.
- *
- * @since 1.3.3
- * @access private
- * @method _previewCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A preview field element.
- * @param {Object} e An event object.
- */
- _previewCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- property = preview.property,
- unit = this._getPreviewCSSUnit( preview, field, e ),
- input = $( e.target ),
- subVals = preview.substitute_values, /* substitute the css value for a staticly-defined alternative */
- rawVal = input.val(),
- value = subVals && Object.keys( subVals ).includes( rawVal ) ? subVals[rawVal] : rawVal,
- responsive = input.closest( '.fl-field-responsive-setting' ).length ? true : false,
- important = preview.important && '' !== value ? ' !important' : '';
- if ( property.indexOf( 'image' ) > -1 && value ) {
- value = 'url(' + value + ')';
- } else if ( '%' === unit && 'opacity' === property ) {
- value = parseInt( value ) / 100;
- } else if ( '' !== value && ! isNaN(value) ) {
- value += unit;
- }
- if ( preview.format_value ) {
- value = wp.i18n.sprintf( preview.format_value, value )
- }
- /**
- * Support for sub_value key when previewing compound fields.
- */
- if ( undefined !== preview.sub_value ) {
- const name = input.attr('name')
- if ( 'string' === typeof preview.sub_value && ! name.endsWith( `[${preview.sub_value}]` ) ) {
- return
- } else if ( 'object' === typeof preview.sub_value && ! name.includes(`[${preview.sub_value.setting_name}]`) ) {
- return
- }
- }
- /**
- * Support for enabled property
- * Meant to closely match FLBuilderCSS::is_rule_enabled()
- */
- if ( 'boolean' === typeof preview.enabled ) {
- return preview.enabled
- } else if ( preview.enabled && 'object' === typeof preview.enabled ) {
- const form = $( '.fl-builder-settings:visible', window.parent.document )
- const settings = FLBuilder._getSettings( form )
- // Test each setting in the object
- for( let name in preview.enabled ) {
- const test = preview.enabled[name]
- if ( 'object' === typeof test ) {
- if ( 'nearest_value' in test ) {
- const mode = FLBuilderResponsiveEditing._mode
- const inherited = this.getInheritedSettingValue( name, mode, settings )
- if ( 'string' === typeof test.nearest_value && test.nearest_value !== inherited ) {
- return
- } else if ( Array.isArray( test.nearest_value ) && ! test.nearest_value.includes( inherited ) ) {
- return
- }
- }
- } else if ( Array.isArray( preview.enabled[name] ) ) {
- if ( ! preview.enabled[name].some( v => v === settings[name] ) ) {
- return
- }
- } else if ( preview.enabled[name] !== settings[name] ) {
- return
- }
- }
- }
- if ( Array.isArray( property ) ) {
- for( let i in property ) {
- this.updateCSSRule( selector, property[i], value + important, responsive );
- }
- } else {
- this.updateCSSRule( selector, property, value + important, responsive );
- }
- },
- /**
- * Find the nearest inherited value for a particular setting from a given breakpoint.
- */
- getInheritedSettingValue: function( settingBaseName, currentBreakpoint, settings ) {
- const isDefault = '' === currentBreakpoint || 'default' === currentBreakpoint
- let name = isDefault ? settingBaseName : `${settingBaseName}_${currentBreakpoint}`
- if ( undefined !== settings[name] ) {
- return settings[name]
- }
- // Meant to be in reverse (most-to-least specific)
- const current = 'default' === currentBreakpoint ? '' : currentBreakpoint
- let breakpoints = [ 'responsive', 'medium', 'large', '' ]
- let i = breakpoints.indexOf( current )
- if ( -1 === i ) {
- return null
- }
- breakpoints = breakpoints.slice(i)
- for( let i in breakpoints ) {
- const breakpoint = breakpoints[i]
- name = '' === breakpoint ? settingBaseName : `${settingBaseName}_${breakpoint}`
- if ( undefined !== settings[name] && '' !== settings[name] ) {
- return settings[name]
- }
- }
- return null
- },
- /* Border Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a border preview.
- *
- * @since 2.2
- * @access private
- * @method _previewBorderCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A field object.
- * @param {Object} e An event object.
- */
- _previewBorderCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- target = $( e.target ),
- field = target.closest( '.fl-field' ),
- wrap = target.closest( '.fl-compound-field-setting' ),
- property = wrap.data( 'property' ),
- value = target.val(),
- unit = wrap.find( '.fl-field-unit-select' ),
- responsive = target.closest( '.fl-field-responsive-setting' ).length ? true : false,
- important = preview.important && '' !== value ? ' !important' : '';
- preview.property = property;
- if ( 'border-color' === property ) {
- this._previewColorCSS( preview, field, e );
- } else if ( 'border-width' === property || 'border-radius' === property ) {
- this._previewDimensionCSS( preview, field, e );
- } else if ( 'box-shadow' === property ) {
- this._previewShadowCSS( preview, wrap, e );
- } else {
- if ( 'border-style' === property ) {
- field.find( '.fl-border-field-width input:visible' ).trigger( 'input' );
- }
- this.updateCSSRule( selector, property, value + important, responsive );
- }
- },
- /* Color Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a color preview.
- *
- * @since 1.3.3
- * @access private
- * @method _previewColorCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A field object.
- * @param {Object} e An event object.
- */
- _previewColorCSS: function(preview, field, e)
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- input = $(e.target),
- value = input.val(),
- responsive = input.closest( '.fl-field-responsive-setting' ).length ? true : false,
- important = preview.important && '' !== value ? ' !important' : '';
- if ( '' !== value && value.indexOf( 'rgb' ) < 0 && value.indexOf( 'var' ) < 0 ) {
- value = '#' + value;
- }
- this.updateCSSRule( selector, preview.property, value + important, responsive );
- },
- /* Dimension Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a dimension field preview.
- *
- * @since 2.0.7
- * @access private
- * @method _previewDimensionCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A preview field element.
- * @param {Object} e An event object.
- */
- _previewDimensionCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- property = preview.property,
- key = field.attr( 'id' ).replace( 'fl-field-', '' ),
- dimension = $( e.target ).data( 'unit' ),
- value = this._getDimensionValue( preview, field, dimension, e ),
- responsive = field.find( '.fl-field-responsive-setting' ).length ? true : false,
- important = preview.important && '' !== value ? ' !important' : '';
- if ( 'border-radius' === property ) {
- property = 'border-' + dimension.replace( '_', '-' ) + '-radius';
- } else if ( 'border-width' === property ) {
- property = 'border-' + dimension + '-width';
- } else if ( 'gap' === property ) {
- property = dimension + '-' + property;
- } else {
- property = property + '-' + dimension;
- }
- this.updateCSSRule( selector, property, value + important, responsive );
- if ( 'margin' === key || 'padding' === key || 'border' === key ) {
- if ( this.elements.node.find('.fl-bg-slideshow').length ) {
- FLBuilder._resizeLayout();
- }
- }
- },
- /**
- * Get a preview dimension value for a property.
- *
- * @since 2.2
- * @access private
- * @param {Object} preview A preview object.
- * @param {Object} field A preview field element.
- * @param {String} dimension The dimension key.
- * @param {Object} e An event object.
- * @return {String}
- */
- _getDimensionValue: function( preview, field, dimension, e )
- {
- var input = $( e.target ),
- value = input.val(),
- unit = '';
- value = value.toLowerCase().replace( /[^a-z0-9%.\-]/g, '' );
- if ( null !== value && '' !== value && ! isNaN( value ) ) {
- unit = this._getPreviewCSSUnit( preview, field, e );
- value = parseFloat( value ) + ( unit ? unit : 'px' );
- } else if ( input.attr( 'placeholder' ) ) {
- unit = this._getPreviewCSSUnit( preview, field, e );
- value = parseFloat( input.attr( 'placeholder' ) ) + ( unit ? unit : 'px' );
- }
- return value;
- },
- /**
- * Get the value's unit for a CSS preview.
- *
- * @since 2.2
- * @access private
- * @param {Object} preview A preview object.
- * @param {Object} field A preview field element.
- * @param {Object} e An event object.
- * @return {String}
- */
- _getPreviewCSSUnit: function( preview, field, e )
- {
- var input = $( e.target ),
- mode = FLBuilderResponsiveEditing._mode,
- compound = input.closest( '.fl-compound-field-setting' ).length ? true : false,
- responsive = input.closest( '.fl-field-responsive-setting' ).length ? true : false,
- select = null;
- if ( compound ) {
- select = input.closest( '.fl-compound-field-setting' ).find( '.fl-field-unit-select' );
- } else if ( responsive ) {
- select = input.closest( '.fl-field-responsive-setting' ).find( '.fl-field-unit-select' );
- } else {
- select = field.find( '.fl-field-unit-select' );
- }
- if ( select && select.length ) {
- if ( 'SELECT' === select.prop( 'tagName' ) ) {
- return select.val();
- } else {
- return select.text();
- }
- } else if ( preview.unit ) {
- return preview.unit;
- }
- return '';
- },
- /**
- * Initializes the custom unit select for a field.
- *
- * @since 2.2
- * @access private
- * @method _initFieldUnitSelect
- * @param {Object} field
- */
- _initFieldUnitSelect: function(field)
- {
- field.find( '.fl-field-unit-select' ).on( 'change', function() {
- var select = $( this ),
- responsive = select.closest( '.fl-field-responsive-setting' ),
- field = select.closest( '.fl-field' );
- if ( responsive.length ) {
- responsive.find( 'input' ).trigger( 'input' );
- } else {
- field.find( 'input' ).trigger( 'input' );
- }
- } );
- },
- /* Gradient Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a gradient preview.
- *
- * @since 2.2
- * @access private
- * @method _previewGradientCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A field object.
- * @param {Object} e An event object.
- */
- _previewGradientCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- type = field.find( '.fl-gradient-picker-type-select' ).val(),
- angle = field.find( '.fl-gradient-picker-angle' ).val(),
- position = field.find( '.fl-gradient-picker-position' ).val(),
- colors = field.find( '.fl-color-picker-value' ),
- stops = field.find( '.fl-gradient-picker-stop input' ),
- values = [],
- value = '',
- important = '';
- colors.each( function( i ) {
- var color = $( this ).val(),
- stop = stops.eq( i ).val();
- if ( '' === color ) {
- color = 'rgba(255,255,255,0)';
- }
- if ( color.indexOf( 'rgb' ) < 0 ) {
- color = '#' + color;
- }
- if ( isNaN( stop ) ) {
- stop = 0;
- }
- values.push( color + ' ' + stop + '%' );
- } );
- values = values.join( ', ' );
- if ( 'linear' === type ) {
- if ( isNaN( angle ) ) {
- angle = 0;
- }
- value = 'linear-gradient(' + angle + 'deg, ' + values + ')';
- } else {
- value = 'radial-gradient(at ' + position + ', ' + values + ')';
- }
- important = preview.important && '' !== value ? ' !important' : '';
- this.updateCSSRule( selector, preview.property, value + important );
- },
- /* Shadow Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a shadow preview.
- *
- * @since 2.2
- * @access private
- * @method _previewShadowCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A field object.
- * @param {Object} e An event object.
- */
- _previewShadowCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- color = field.find( '.fl-shadow-field-color input' ).val(),
- horizontal = field.find( '.fl-shadow-field-horizontal input' ).val(),
- vertical = field.find( '.fl-shadow-field-vertical input' ).val(),
- blur = field.find( '.fl-shadow-field-blur input' ).val(),
- spread = field.find( '.fl-shadow-field-spread input' ).val(),
- hasSpread = field.find( '.fl-shadow-field-spread input' ).length ? true : false,
- responsive = $( e.target ).closest( '.fl-field-responsive-setting' ).length ? true : false,
- value = '',
- important = '';
- if ( '' !== color ) {
- if ( '' === horizontal ) {
- horizontal = 0;
- }
- if ( '' === vertical ) {
- vertical = 0;
- }
- if ( '' === blur ) {
- blur = 0;
- }
- if ( '' === spread ) {
- spread = 0;
- }
- if ( color.indexOf( 'rgb' ) < 0 ) {
- color = '#' + color;
- }
- value = horizontal + 'px ';
- value += vertical + 'px ';
- value += blur + 'px ';
- if ( hasSpread ) {
- value += spread + 'px ';
- }
- value += color;
- value += important;
- }
- important = preview.important && '' !== value ? ' !important' : '';
- this.updateCSSRule( selector, preview.property, value, responsive );
- },
- /* Typography Field CSS Preview
- ----------------------------------------------------------*/
- /**
- * Updates the CSS rule for a typography preview.
- *
- * @since 2.2
- * @access private
- * @method _previewTypographyCSS
- * @param {Object} preview A preview object.
- * @param {Object} field A field object.
- * @param {Object} e An event object.
- */
- _previewTypographyCSS: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- target = $( e.target ),
- field = target.closest( '.fl-field' ),
- wrap = target.closest( '.fl-compound-field-setting' ),
- property = wrap.data( 'property' ),
- value = target.val(),
- unit = wrap.find( '.fl-field-unit-select' ),
- responsive = target.closest( '.fl-field-responsive-setting' ).length ? true : false,
- important = preview.important && '' !== value ? ' !important' : '';
- if ( 'font-family' === property ) {
- preview.id = field.attr( 'id' );
- this._previewFont( preview, { delegateTarget: wrap } );
- } else if ( 'text-shadow' === property ) {
- preview.property = 'text-shadow';
- this._previewShadowCSS( preview, wrap, e );
- } else {
- if ( unit.length && '' !== value ) {
- if ( 'vw' === unit.val() ) {
- // calc(14px + 5vw);
- value = 'calc(' + FLBuilderConfig.global.responsive_base_fontsize + 'px + ' + value + 'vw)'
- } else {
- value += 'SELECT' === unit.prop( 'tagName' ) ? unit.val() : 'px';
- }
- }
- this.updateCSSRule( selector, property, value + important, responsive );
- }
- },
- /* Widget Preview
- ----------------------------------------------------------*/
- /**
- * Initializes the attribute preview for a field.
- *
- * @since 2.2
- * @access private
- * @method _initFieldAttributePreview
- * @param {Object} field The field to preview.
- */
- _initFieldAttributePreview: function(field)
- {
- var preview = field.data('preview'),
- attrName = preview.attribute,
- input = field.find('input'),
- value = field.val(),
- formatValue = window[preview.format_callback];
- var fullSelector = this._getPreviewSelector( this.classes.node, preview.selector ),
- element = $( fullSelector );
- var callback = this._previewAttribute.bind( this, input, element, attrName, formatValue );
- input.on('change', callback );
- input.on('keyup', callback );
- input.on('input', callback );
- },
- /**
- * Runs a real time preview for attribute fields.
- *
- * @since 2.2
- * @access private
- * @method _previewAttribute
- * @param {Object} input A ref to the input control.
- * @param {Object} element A ref to the selected element within the node.
- * @param String attrName The name of the attribute to be changed.
- */
- _previewAttribute: function( input, element, attrName, formatValue ) {
- var value = input.val();
- if ( 'function' === typeof formatValue ) {
- value = formatValue( value );
- }
- for (i = 0; i < element.length; i++) {
- element[i].setAttribute( attrName, value );
- }
- },
- /**
- * Initializes the preview for a WordPress widget.
- *
- * @since 1.3.3
- * @access private
- * @method _initFieldWidgetPreview
- * @param {Object} field A field object.
- */
- _initFieldWidgetPreview: function(field)
- {
- var callback = $.proxy(this.delayPreview, this);
- field.find('input').on('keyup', callback);
- field.find('input[type=checkbox]').on('click', callback);
- field.find('textarea').on('keyup', callback);
- field.find('select').on('change', callback);
- },
- /* Animation Field Preview
- ----------------------------------------------------------*/
- /**
- * Initializes animation previews.
- *
- * @since 2.2
- * @access private
- * @method _initFieldAnimationPreview
- */
- _initFieldAnimationPreview: function( preview, field )
- {
- field.find( '.fl-animation-field-style select' ).on( 'change', $.proxy( this._previewAnimationField, this, preview, field ) );
- field.find( '.fl-animation-field-duration input' ).on( 'input', $.proxy( this._previewAnimationField, this, preview, field ) );
- },
- /**
- * Previews an animation field.
- *
- * @since 2.2
- * @access private
- * @method _previewAnimationField
- */
- _previewAnimationField: function( preview, field, e )
- {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- element = $( selector ),
- animation = field.find( '.fl-animation-field-style select' ),
- duration = field.find( '.fl-animation-field-duration input' ),
- options = animation[0].options;
- element.removeClass( 'fl-animated' );
- element.removeClass( 'fl-animation' );
- element.css( 'animation-duration', '' );
- for ( var i = 0; i < options.length; i++ ) {
- element.removeClass( 'fl-' + options[i].value );
- }
- if ( '' !== animation.val() ) {
- element.addClass( 'fl-animation' );
- element.addClass( 'fl-' + animation.val() );
- element.data( 'animation-delay', 0 );
- element.data( 'animation-duration', duration.val() );
- }
- FLBuilderLayout._doModuleAnimation.apply( element );
- },
- _previewFieldObjectFit: function( preview, field, e ) {
- const selector = this._getPreviewSelector( this.classes.node, preview.selector ),
- element = $( selector ).closest('.fl-module').get(0),
- className = 'fl-fill-container',
- fit = field.find( '.fl-button-group-field input' ).val();
- if ( '' === fit && element.classList.contains( className ) ) {
- element.classList.remove( className )
- }
- if ( '' !== fit && ! element.classList.contains( className ) ) {
- element.classList.add( className )
- }
- },
- /**
- * Returns a formatted selector string for a preview.
- *
- * @since 1.6.1
- * @access private
- * @method _getPreviewSelector
- * @param {String} selector A CSS selector string.
- * @return {String}
- */
- _getPreviewSelector: function( prefix, selector )
- {
- return FLBuilderPreview.getFormattedSelector.call( this, prefix, selector );
- },
- /**
- * Converts words in a string to upper case.
- *
- * @since 2.2
- * @method toUpperCaseWords
- * @param {String} string
- * @return {String}
- */
- toUpperCaseWords: function( string ) {
- return string.charAt( 0 ).toUpperCase() + string.slice( 1 );
- },
- };
- /**
- * Format a color value for use with CSS
- * @since 2.2
- * @method formatColor
- * @param {String} value
- * @return {String}
- */
- FLBuilderPreview.formatColor = function( value ) {
- if ( '' !== value && ( value.indexOf( 'rgb' ) < 0 && value.indexOf( 'url' ) < 0 ) ) {
- value = '#' + value;
- }
- return value;
- };
- FLBuilderPreviewCallbacks = {
- /**
- * Setup the shape when selected
- */
- previewShape: function( args, e ) {
- var position = args.preview.position,
- prefix = args.preview.prefix,
- form = args.form,
- yOrientationInputName = prefix + 'transform[][scaleYSign]';
- yOrientation = form.find('input[name="' + yOrientationInputName + '"]');
- if ( 'bottom' === position ) {
- yOrientation.val('invert');
- } else {
- yOrientation.val('');
- }
- yOrientation.trigger('change');
- // Cause refresh
- this.delayPreview();
- },
- /**
- * Preview the layer's width, height and Y offset
- */
- previewShapeLayerSize: function( args, e ) {
- var values = args.getValues(),
- unitValue = values.unit,
- width = values.props.width,
- height = values.props.height,
- top = values.props.top,
- /* static data from field config */
- prefix = args.preview.prefix,
- position = args.preview.position,
- layerSelector = this._getPreviewSelector( this.classes.node, '.fl-builder-' + position + '-edge-layer' ),
- shapeSelector = layerSelector + ' > *',
- /* the align field */
- align = args.form.find('[name="' + prefix + 'align"]'),
- alignValue = align.val(),
- alignParts = alignValue.split(' '),
- yAlign = alignParts[0],
- xAlign = alignParts[1],
- /* calculated props */
- shapeField = args.form.find('[name="' + prefix + 'shape"]'),
- shapeValue = shapeField.val(),
- shapePreset = FLBuilderConfig.presets.shape[shapeValue]
- shapeProps = {};
- // Defaults
- shapeProps.width = '100%';
- shapeProps.left = 'auto';
- shapeProps.right = 'auto';
- shapeProps.height = 'auto';
- shapeProps.top = 'auto';
- shapeProps.bottom = 'auto';
- // Width
- if ( width ) {
- shapeProps.width = width + unitValue;
- var offset = ( width / 2 ) + unitValue;
- switch( xAlign ) {
- case 'left':
- shapeProps.left = '0';
- shapeProps.right = 'auto';
- break;
- case 'right':
- shapeProps.left = 'auto';
- shapeProps.right = '0';
- break;
- case 'center':
- shapeProps.left = 'calc( 50% - ' + offset + ')';
- shapeProps.right = 'auto';
- break;
- }
- }
- this.updateCSSRule( shapeSelector, 'width', shapeProps.width );
- this.updateCSSRule( shapeSelector, 'left', shapeProps.left );
- this.updateCSSRule( shapeSelector, 'right', shapeProps.right );
- // Height
- // We need a height for vertical centering to work, but it doesn't have to be explicit.
- var heightOffset;
- if ( height ) {
- heightOffset = ( height / 2 ) + unitValue;
- } else if ( width ) {
- var viewBoxHeight = shapePreset.data.viewBox.width,
- impliedHeight = ( width / viewBoxHeight ) * 100;
- heightOffset = ( impliedHeight / 2 ) + unitValue ;
- } else {
- heightOffset = ''
- }
- if ( height ) {
- shapeProps.height = height + unitValue;
- }
- switch( yAlign ) {
- case 'top':
- shapeProps.top = '0';
- shapeProps.bottom = 'auto';
- break;
- case 'bottom':
- shapeProps.top = 'auto';
- shapeProps.bottom = '0';
- break;
- case 'center':
- shapeProps.top = 'calc( 50% - ' + heightOffset + ')';
- shapeProps.bottom = 'auto';
- break;
- }
- this.updateCSSRule( shapeSelector, 'height', shapeProps.height + ' !important' );
- this.updateCSSRule( shapeSelector, 'top', shapeProps.top );
- this.updateCSSRule( shapeSelector, 'bottom', shapeProps.bottom );
- // Y offset
- if ( '' === top ) {
- this.updateCSSRule( layerSelector, position, '0' );
- } else {
- this.updateCSSRule( layerSelector, position, top + unitValue );
- }
- },
- previewShapeAlign: function( args, e ) {
- // Let width and height preview do the work.
- var prefix = args.preview.prefix,
- widthField = args.form.find('[name="' + prefix + 'size_width"]');
- widthField.trigger('input');
- },
- /**
- * Process the fill style when toggled
- *
- * @param {Object} args - a collection of helper references setup on field init
- * @param Event e - the event passed by the event listener
- * @return void
- */
- previewShapeFillStyle: function( args, e ) {
- var value = args.input.val(),
- preview = args.preview,
- prefix = args.preview.prefix,
- linearGradientId = 'fl-row-' + args.nodeID + '-' + prefix + '-linear-gradient',
- radialGradientId = 'fl-row-' + args.nodeID + '-' + prefix + '-radial-gradient',
- patternId = 'fl-row-' + args.nodeID + '-' + prefix + '-pattern',
- form = args.form;
- if ( 'undefined' !== typeof value ) {
- var selector = this._getPreviewSelector( this.classes.node, preview.selector );
- switch( value ) {
- case 'color':
- var colorValue = form.find('[name=' + prefix + 'fill_color]').val();
- this.updateCSSRule( selector, 'fill', FLBuilderPreview.formatColor( colorValue ) );
- break;
- case 'gradient':
- var gradientField = form.find('#fl-field-' + prefix + 'fill_gradient'),
- gradientType = gradientField.find('select[name$="[type]"]').val();
- var gradientId = 'radial' === gradientType ? radialGradientId : linearGradientId ;
- this.updateCSSRule( selector, 'fill', 'url(#' + gradientId + ')' );
- break;
- case 'pattern':
- var fill = 'url(#' + patternId + ')';
- this.updateCSSRule( selector, 'fill', fill );
- }
- }
- },
- /**
- * Process the gradient control values
- *
- * @param {Object} args - a collection of helper references setup on field init
- * @param Event e - the event passed by the event listener
- * @return void
- */
- previewShapeGradientFill: function( args, e ) {
- var values = args.getValues(),
- node = args.node,
- preview = args.preview,
- layerSelector = '.fl-builder-' + preview.position + '-edge-layer',
- gradientDef = node.find( layerSelector + ' ' + values.type + 'Gradient' ),
- fill = 'url(#' + gradientDef.attr('id') + ')',
- shapeSelector = this._getPreviewSelector( this.classes.node, layerSelector + ' .fl-shape' );
- this.updateCSSRule( shapeSelector, 'fill', fill );
- // Set stops
- var stopEls = gradientDef.find('stop');
- for( var i in values.stops ) {
- var stopVal = values.stops[i],
- stop = stopEls.eq(i),
- color = stopVal.color,
- offset = stopVal.stop,
- opacity = 1;
- if ( color.indexOf( 'rgba' ) === 0 ) {
- var rawValues = color.substring( color.indexOf('(') + 1, color.lastIndexOf(')') ).split( /,\s*/ );
- opacity = rawValues.pop();
- color = 'rgb(' + rawValues.join(',') + ')';
- }
- stop.attr('stop-color', FLBuilderPreview.formatColor( color ) );
- stop.attr('stop-opacity', opacity );
- stop.attr('offset', offset + '%' );
- }
- // Set Angle
- if ( 'linear' === values.type && 'undefined' !== typeof gradientDef[0] ) {
- gradientDef[0].setAttribute( 'gradientTransform', 'rotate(' + values.angle + ' .5 .5 )' );
- }
- // Set Position
- if ( 'radial' === values.type ) {
- // Split string by space
- parts = values.position.split(' ');
- var x = parts[0],
- y = parts[1],
- cx,
- cy,
- r;
- switch( x ) {
- case 'top':
- case 'left':
- cx = 0;
- break;
- case 'center':
- cx = .5;
- break;
- case 'bottom':
- case 'right':
- cx = 1;
- break;
- }
- switch( y ) {
- case 'top':
- case 'left':
- cy = 0;
- break;
- case 'center':
- cy = .5;
- break;
- case 'bottom':
- case 'right':
- cy = 1;
- break;
- }
- r = .5;
- if ( cx !== .5 || cy !== .5 ) r = 1;
- gradientDef.attr( 'cx', cx );
- gradientDef.attr( 'cy', cy );
- gradientDef.attr( 'r', r );
- }
- },
- /**
- * Process the transform control values
- *
- * @param {Object} args - a collection of helper references setup on field init
- * @param Event e - the event passed by the event listener
- * @return void
- */
- previewShapeTransform: function ( args, e ) {
- var form = args.form,
- preview = args.preview,
- prefix = preview.prefix,
- layerSelector = this._getPreviewSelector( this.classes.node, preview.selector ),
- shapeSelector = layerSelector + ' > *',
- values = args.getValues(),
- shapeTransforms = [];
- Object.keys( values ).map( function( prop ) {
- var value = values[prop];
- var unit = '',
- sign = '';
- switch( prop ) {
- case 'scaleXSign':
- case 'scaleYSign':
- return;
- case 'scaleX':
- case 'scaleY':
- if ( !value || '' === value || 0 === value ) value = '1';
- sign = 'scaleX' === prop ? values['scaleXSign'] : values['scaleYSign'] ; // Positive or negative?
- if ( 'invert' === sign ) {
- value = -Math.abs( value );
- } else {
- value = Math.abs( value );
- }
- shapeTransforms.push( prop + '(' + value + ')' ); // scale has no unit
- break;
- case 'translateX':
- case 'translateY':
- if ( value ) {
- unit = 'px';
- shapeTransforms.push( prop + '(' + value + unit + ')' );
- }
- break;
- case 'skewX':
- case 'skewY':
- if ( value ) {
- unit = 'deg';
- shapeTransforms.push( prop + '(' + value + unit + ')' );
- }
- break;
- case 'rotate':
- unit = 'deg';
- if ( value !== '' && value !== '0' ) {
- shapeTransforms.push( 'rotate(' + value + unit + ')' );
- }
- break;
- }
- } );
- this.updateCSSRule( shapeSelector, 'transform', shapeTransforms.join(' ') );
- },
- }
- })(jQuery);
|