| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697 |
- /* global wpforms_builder, wpf, jconfirm, wpforms_panel_switch, Choices, WPForms, WPFormsFormEmbedWizard, wpCookies, tinyMCE */
- var WPFormsBuilder = window.WPFormsBuilder || ( function( document, window, $ ) {
- var s,
- $builder,
- elements = {};
- /**
- * Whether to show the close confirmation dialog or not.
- *
- * @since 1.6.0
- *
- * @type {boolean}
- */
- var closeConfirmation = true;
- /**
- * A field is adding.
- *
- * @since 1.7.1
- *
- * @type {boolean}
- */
- var adding = false;
- var app = {
- settings: {
- spinner: '<i class="wpforms-loading-spinner"></i>',
- spinnerInline: '<i class="wpforms-loading-spinner wpforms-loading-inline"></i>',
- tinymceDefaults: { tinymce: { toolbar1: 'bold,italic,underline,blockquote,strikethrough,bullist,numlist,alignleft,aligncenter,alignright,undo,redo,link' }, quicktags: true },
- pagebreakTop: false,
- pagebreakBottom: false,
- upload_img_modal: false,
- },
- /**
- * Start the engine.
- *
- * @since 1.0.0
- */
- init: function() {
- var that = this;
- wpforms_panel_switch = true;
- s = this.settings;
- // Document ready.
- $( app.ready );
- // Page load.
- $( window ).on( 'load', function() {
- // In the case of jQuery 3.+, we need to wait for a ready event first.
- if ( typeof $.ready.then === 'function' ) {
- $.ready.then( app.load );
- } else {
- app.load();
- }
- } );
- $( window ).on( 'beforeunload', function() {
- if ( ! that.formIsSaved() && closeConfirmation ) {
- return wpforms_builder.are_you_sure_to_close;
- }
- } );
- },
- /**
- * Page load.
- *
- * @since 1.0.0
- */
- load: function() {
- app.hideLoadingOverlay();
- // Maybe display informational modal.
- if ( wpforms_builder.template_modal_display == '1' && 'fields' === wpf.getQueryString('view') ) {
- $.alert( {
- title: wpforms_builder.template_modal_title,
- content: wpforms_builder.template_modal_msg,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons: {
- confirm: {
- text: wpforms_builder.close,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- }
- },
- /**
- * Document ready.
- *
- * @since 1.0.0
- */
- ready: function() {
- if ( app.isVisitedViaBackButton() ) {
- location.reload();
- return;
- }
- // Cache builder element.
- $builder = $( '#wpforms-builder' );
- // Cache other elements.
- elements.$fieldOptions = $( '#wpforms-field-options' );
- elements.$sortableFieldsWrap = $( '.wpforms-field-wrap' );
- elements.$noFieldsOptions = $( '.wpforms-no-fields-holder .no-fields' );
- elements.$noFieldsPreview = $( '.wpforms-no-fields-holder .no-fields-preview' );
- elements.$addFieldsButtons = $( '.wpforms-add-fields-button' ).not( '.not-draggable' ).not( '.warning-modal' ).not( '.education-modal' );
- // Remove Embed button if builder opened in popup.
- if ( app.isBuilderInPopup() ) {
- $( '#wpforms-embed' ).remove();
- $( '#wpforms-preview-btn' ).addClass( 'wpforms-alone' );
- }
- app.loadMsWinCSS();
- // Bind all actions.
- app.bindUIActions();
- // Trigger initial save for new forms.
- var newForm = wpf.getQueryString( 'newform' );
- if ( newForm ) {
- app.formSave( false );
- }
- // Setup/cache some vars not available before
- s.formID = $( '#wpforms-builder-form' ).data( 'id' );
- s.pagebreakTop = $( '.wpforms-pagebreak-top' ).length;
- s.pagebreakBottom = $( '.wpforms-pagebreak-bottom' ).length;
- // Disable implicit submission for every form inside the builder.
- // All form values are managed by JS and should not be submitted by pressing Enter.
- $builder.on( 'keypress', '#wpforms-builder-form :input:not(textarea)', function( e ) {
- if ( e.keyCode === 13 ) {
- e.preventDefault();
- }
- } );
- // If there is a section configured, display it.
- // Otherwise we show the first panel by default.
- $( '.wpforms-panel' ).each( function( index, el ) {
- var $this = $( this ),
- $configured = $this.find( '.wpforms-panel-sidebar-section.configured' ).first();
- if ( $configured.length ) {
- var section = $configured.data( 'section' );
- $configured.addClass( 'active' );
- $this.find( '.wpforms-panel-content-section-' + section ).show().addClass( 'active' );
- $this.find( '.wpforms-panel-content-section-default' ).hide();
- } else {
- $this.find( '.wpforms-panel-content-section:first-of-type' ).show().addClass( 'active' );
- $this.find( '.wpforms-panel-sidebar-section:first-of-type' ).addClass( 'active' );
- }
- } );
- app.loadEntryPreviewFields();
- // Drag and drop sortable elements.
- app.fieldSortable();
- app.fieldChoiceSortable( 'select' );
- app.fieldChoiceSortable( 'radio' );
- app.fieldChoiceSortable( 'checkbox' );
- app.fieldChoiceSortable( 'payment-multiple' );
- app.fieldChoiceSortable( 'payment-checkbox' );
- app.fieldChoiceSortable( 'payment-select' );
- // Load match heights.
- $( '.wpforms-setup-templates.core .wpforms-template-inner' ).matchHeight( {
- byRow: false,
- } );
- $( '.wpforms-setup-templates.additional .wpforms-template-inner' ).matchHeight( {
- byRow: false,
- } );
- // Set field group visibility.
- $( '.wpforms-add-fields-group' ).each( function( index, el ) {
- app.fieldGroupToggle( $( this ), 'load' );
- } );
- app.registerTemplates();
- // Trim long form titles.
- app.trimFormTitle();
- // Load Tooltips.
- wpf.initTooltips();
- // Load Color Pickers.
- app.loadColorPickers();
- // Hide/Show CAPTCHA in form.
- app.captchaToggle();
- // Confirmations initial setup
- app.confirmationsSetup();
- // Notification settings.
- app.notificationToggle();
- app.notificationsByStatusAlerts();
- // Secret builder hotkeys.
- app.builderHotkeys();
- // Clone form title to setup page.
- $( '#wpforms-setup-name' ).val( $( '#wpforms-panel-field-settings-form_title' ).val() );
- // jquery-confirm defaults.
- jconfirm.defaults = {
- closeIcon: false,
- backgroundDismiss: false,
- escapeKey: true,
- animationBounce: 1,
- useBootstrap: false,
- theme: 'modern',
- boxWidth: '400px',
- animateFromElement: false,
- content: wpforms_builder.something_went_wrong,
- };
- app.dropdownField.init();
- app.initSomeFieldOptions();
- app.dismissNotice();
- },
- /**
- * Load Microsoft Windows specific stylesheet.
- *
- * @since 1.6.8
- */
- loadMsWinCSS: function() {
- var ua = navigator.userAgent;
- // Detect OS & browsers.
- if (
- ua.indexOf( 'Windows' ) < 0 || (
- ua.indexOf( 'Chrome' ) < 0 &&
- ua.indexOf( 'Firefox' ) < 0
- )
- ) {
- return;
- }
- $( '<link>' )
- .appendTo( 'head' )
- .attr( {
- type: 'text/css',
- rel: 'stylesheet',
- href: wpforms_builder.ms_win_css_url,
- } );
- },
- /**
- * Builder was visited via back button in browser.
- *
- * @since 1.6.5
- *
- * @returns {boolean} True if the builder was visited via back button in browser.
- */
- isVisitedViaBackButton: function() {
- if ( ! performance ) {
- return false;
- }
- var isVisitedViaBackButton = false;
- performance.getEntriesByType( 'navigation' ).forEach( function( nav ) {
- if ( nav.type === 'back_forward' ) {
- isVisitedViaBackButton = true;
- }
- } );
- return isVisitedViaBackButton;
- },
- /**
- * Remove loading overlay.
- *
- * @since 1.6.8
- */
- hideLoadingOverlay: function() {
- var $overlay = $( '#wpforms-builder-overlay' );
- $overlay.addClass( 'fade-out' );
- setTimeout( function() {
- $overlay.hide();
- }, 250 );
- },
- /**
- * Show loading overlay.
- *
- * @since 1.6.8
- */
- showLoadingOverlay: function() {
- var $overlay = $( '#wpforms-builder-overlay' );
- $overlay.removeClass( 'fade-out' );
- $overlay.show();
- },
- /**
- * Initialize some fields options controls.
- *
- * @since 1.6.3
- */
- initSomeFieldOptions: function() {
- // Show a toggled options groups.
- app.toggleAllOptionGroups( $builder );
- // Date/Time field Date type option.
- $builder.find( '.wpforms-field-option-row-date .type select' ).trigger( 'change' );
- },
- /**
- * Dropdown field component.
- *
- * @since 1.6.1
- */
- dropdownField: {
- /**
- * Field configuration.
- *
- * @since 1.6.1
- */
- config: {
- modernClass: 'choicesjs-select',
- args: {
- searchEnabled: false,
- searchChoices: false,
- renderChoiceLimit : 1,
- shouldSort: false,
- callbackOnInit: function() {
- var $element = $( this.containerOuter.element ),
- $previewSelect = $element.closest( '.wpforms-field' ).find( 'select' );
- // Turn off disabled styles.
- if ( $element.hasClass( 'is-disabled' ) ) {
- $element.removeClass( 'is-disabled' );
- }
- // Disable instances on the preview panel.
- if ( $previewSelect.is( '[readonly]' ) ) {
- this.disable();
- $previewSelect.prop( 'disabled', false );
- }
- if ( this.passedElement.element.multiple ) {
- // Hide a placeholder if field has selected choices.
- if ( this.getValue( true ).length ) {
- $( this.input.element ).addClass( 'choices__input--hidden' );
- }
- }
- },
- },
- },
- /**
- * Initialization for field component.
- *
- * @since 1.6.1
- */
- init: function() {
- // Choices.js init.
- $builder.find( '.' + app.dropdownField.config.modernClass ).each( function() {
- app.dropdownField.events.choicesInit( $( this ) );
- } );
- // Multiple option.
- $builder.on(
- 'change',
- '.wpforms-field-option-select .wpforms-field-option-row-multiple input',
- app.dropdownField.events.multiple
- );
- // Style option.
- $builder.on(
- 'change',
- '.wpforms-field-option-select .wpforms-field-option-row-style select, .wpforms-field-option-payment-select .wpforms-field-option-row-style select',
- app.dropdownField.events.applyStyle
- );
- },
- /**
- * Field events.
- *
- * @since 1.6.1
- */
- events: {
- /**
- * Load Choices.js library.
- *
- * @since 1.6.1
- *
- * @param {object} $element jQuery element selector.
- */
- choicesInit: function( $element ) {
- var instance = new Choices( $element[0], app.dropdownField.config.args );
- app.dropdownField.helpers.setInstance( $element, instance );
- app.dropdownField.helpers.addPlaceholderChoice( $element, instance );
- },
- /**
- * Multiple option callback.
- *
- * @since 1.6.1
- *
- * @param {object} event Event object.
- */
- multiple: function( event ) {
- var fieldId = $( this ).closest( '.wpforms-field-option-row-multiple' ).data().fieldId,
- $primary = app.dropdownField.helpers.getPrimarySelector( fieldId ),
- $optionChoicesItems = $( '#wpforms-field-option-row-' + fieldId + '-choices input.default' ),
- $placeholder = $primary.find( '.placeholder' ),
- isDynamicChoices = app.dropdownField.helpers.isDynamicChoices( fieldId ),
- isMultiple = event.target.checked,
- choicesType = isMultiple ? 'checkbox' : 'radio',
- selectedChoices;
- // Add/remove a `multiple` attribute.
- $primary.prop( 'multiple', isMultiple );
- // Change a `Choices` fields type:
- // checkbox - needed for multiple selection
- // radio - needed for single selection
- $optionChoicesItems.prop( 'type', choicesType );
- // Dynamic Choices doesn't have default choices (selected options) - make all as unselected.
- if ( isDynamicChoices ) {
- $primary.find( 'option:selected' ).prop( 'selected', false );
- }
- // Gets default choices.
- selectedChoices = $optionChoicesItems.filter( ':checked' );
- if ( ! isMultiple && selectedChoices.length ) {
- // Uncheck all choices.
- $optionChoicesItems.prop( 'checked', false );
- // For single selection we can choose only one.
- $( selectedChoices.get( 0 ) ).prop( 'checked', true );
- }
- // Toggle selection for a placeholder option based on a select type.
- if ( $placeholder.length ) {
- $placeholder.prop( 'selected', ! isMultiple );
- }
- // Update a primary field.
- app.dropdownField.helpers.update( fieldId, isDynamicChoices );
- },
- /**
- * Apply a style to <select> - modern or classic.
- *
- * @since 1.6.1
- */
- applyStyle: function() {
- var $field = $( this ),
- fieldId = $field.closest( '.wpforms-field-option-row-style' ).data().fieldId,
- fieldVal = $field.val();
- if ( 'modern' === fieldVal ) {
- app.dropdownField.helpers.convertClassicToModern( fieldId );
- } else {
- app.dropdownField.helpers.convertModernToClassic( fieldId );
- }
- },
- },
- helpers: {
- /**
- * Get Modern select options and prepare them for the Classic <select>.
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- */
- convertModernToClassic: function( fieldId ) {
- var $primary = app.dropdownField.helpers.getPrimarySelector( fieldId ),
- isDynamicChoices = app.dropdownField.helpers.isDynamicChoices( fieldId ),
- instance = app.dropdownField.helpers.getInstance( $primary );
- // Destroy the instance of Choices.js.
- instance.destroy();
- // Update a placeholder.
- app.dropdownField.helpers.updatePlaceholderChoice( instance, fieldId );
- // Update choices.
- if ( ! isDynamicChoices ) {
- app.fieldChoiceUpdate( 'select', fieldId );
- }
- },
- /**
- * Convert a Classic to Modern style selector.
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- */
- convertClassicToModern: function( fieldId ) {
- var $primary = app.dropdownField.helpers.getPrimarySelector( fieldId ),
- isDynamicChoices = app.dropdownField.helpers.isDynamicChoices( fieldId );
- // Update choices.
- if ( ! isDynamicChoices ) {
- app.fieldChoiceUpdate( 'select', fieldId );
- }
- // Call a Choices.js initialization.
- app.dropdownField.events.choicesInit( $primary );
- },
- /**
- * Update a primary field.
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- * @param {boolean} isDynamicChoices True if `Dynamic Choices` is turned on.
- */
- update: function( fieldId, isDynamicChoices ) {
- var $primary = app.dropdownField.helpers.getPrimarySelector( fieldId );
- if ( app.dropdownField.helpers.isModernSelect( $primary ) ) {
- // If we had a `Modern` select before, then we need to make re-init - destroy() + init().
- app.dropdownField.helpers.convertModernToClassic( fieldId );
- app.dropdownField.events.choicesInit( $primary );
- } else {
- // Update choices.
- if ( ! isDynamicChoices ) {
- app.fieldChoiceUpdate( 'select', fieldId );
- }
- }
- },
- /**
- * Add a new choice to behave like a placeholder.
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery primary selector.
- * @param {object} instance The instance of Choices.js.
- *
- * @returns {boolean} False if a fake placeholder wasn't added.
- */
- addPlaceholderChoice: function( $jquerySelector, instance ) {
- var fieldId = $jquerySelector.closest( '.wpforms-field' ).data().fieldId,
- hasDefaults = app.dropdownField.helpers.hasDefaults( fieldId );
- if ( app.dropdownField.helpers.isDynamicChoices( fieldId ) ) {
- hasDefaults = false;
- }
- // Already has a placeholder.
- if ( false !== app.dropdownField.helpers.searchPlaceholderChoice( instance ) ) {
- return false;
- }
- // No choices.
- if ( ! instance.config.choices.length ) {
- return false;
- }
- var placeholder = instance.config.choices[0].label,
- isMultiple = $( instance.passedElement.element ).prop( 'multiple' ),
- selected = ! ( isMultiple || hasDefaults );
- // Add a new choice as a placeholder.
- instance.setChoices(
- [
- { value: '', label: placeholder, selected: selected, placeholder: true },
- ],
- 'value',
- 'label',
- false
- );
- // Additional case for multiple select.
- if ( isMultiple ) {
- $( instance.input.element ).prop( 'placeholder', placeholder );
- }
- return true;
- },
- /**
- * Search a choice-placeholder item.
- *
- * @since 1.6.1
- *
- * @param {object} instance The instance of Choices.js.
- *
- * @returns {boolean|object} False if a field doesn't have a choice-placeholder. Otherwise - return choice item.
- */
- searchPlaceholderChoice: function( instance ) {
- var find = false;
- instance.config.choices.forEach( function( item, i, choices ) {
- if ( 'undefined' !== typeof item.placeholder && true === item.placeholder ) {
- find = {
- key: i,
- item: item,
- };
- return false;
- }
- } );
- return find;
- },
- /**
- * Add/update a placeholder.
- *
- * @since 1.6.1
- *
- * @param {object} instance The instance of Choices.js.
- * @param {string} fieldId Field ID.
- */
- updatePlaceholderChoice: function( instance, fieldId ) {
- var $primary = $( instance.passedElement.element ),
- placeholderValue = wpf.sanitizeHTML( $( '#wpforms-field-option-' + fieldId + '-placeholder' ).val() ),
- placeholderChoice = app.dropdownField.helpers.searchPlaceholderChoice( instance ),
- $placeholderOption = {};
- // Get an option with placeholder.
- // Note: `.placeholder` class is skipped when calling Choices.js destroy() method.
- if ( 'object' === typeof placeholderChoice ) {
- $placeholderOption = $( $primary.find( 'option' ).get( placeholderChoice.key ) );
- }
- // We have a placeholder and need to update the UI with it.
- if ( '' !== placeholderValue ) {
- if ( ! $.isEmptyObject( $placeholderOption ) && $placeholderOption.length ) {
- // Update a placeholder option.
- $placeholderOption
- .addClass( 'placeholder' )
- .text( placeholderValue );
- } else {
- // Add a placeholder option.
- $primary.prepend( '<option value="" class="placeholder">' + placeholderValue + '</option>' );
- }
- } else {
- // Remove the placeholder as it's empty.
- if ( $placeholderOption.length ) {
- $placeholderOption.remove();
- }
- }
- },
- /**
- * Is it a `Modern` style dropdown field?
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery primary selector.
- *
- * @returns {boolean} True if it's a `Modern` style select, false otherwise.
- */
- isModernSelect: function( $jquerySelector ) {
- var instance = app.dropdownField.helpers.getInstance( $jquerySelector );
- if ( 'object' !== typeof instance ) {
- return false;
- }
- if ( $.isEmptyObject( instance ) ) {
- return false;
- }
- return instance.initialised;
- },
- /**
- * Save an instance of Choices.js.
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery primary selector.
- * @param {object} instance The instance of Choices.js.
- */
- setInstance: function( $jquerySelector, instance ) {
- $jquerySelector.data( 'choicesjs', instance );
- },
- /**
- * Retrieve an instance of Choices.js.
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery primary selector.
- *
- * @returns {object} The instance of Choices.js.
- */
- getInstance: function( $jquerySelector ) {
- return $jquerySelector.data( 'choicesjs' );
- },
- /**
- * Is `Dynamic Choices` used?
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- *
- * @returns {boolean} True if a `Dynamic Choices` active, false otherwise.
- */
- isDynamicChoices: function( fieldId ) {
- var $fieldOption = $( '#wpforms-field-option-' + fieldId + '-dynamic_choices' );
- if ( ! $fieldOption.length ) {
- return false;
- }
- return '' !== $fieldOption.val();
- },
- /**
- * Is a field has default choices?
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- *
- * @returns {boolean} True if a field has default choices.
- */
- hasDefaults: function( fieldId ) {
- var $choicesList = $( '#wpforms-field-option-row-' + fieldId + '-choices .choices-list' );
- return !! $choicesList.find( 'input.default:checked' ).length;
- },
- /**
- * Retrieve a jQuery selector for the Primary field.
- *
- * @since 1.6.1
- *
- * @param {string} fieldId Field ID.
- *
- * @returns {object} jQuery primary selector.
- */
- getPrimarySelector: function( fieldId ) {
- return $( '#wpforms-field-' + fieldId + ' .primary-input' );
- },
- },
- },
- /**
- * Add number slider events listeners.
- *
- * @since 1.5.7
- *
- * @param {object} $builder JQuery object.
- */
- numberSliderEvents: function( $builder ) {
- // Minimum update.
- $builder.on(
- 'input',
- '.wpforms-field-option-row-min_max .wpforms-input-row .wpforms-number-slider-min',
- app.fieldNumberSliderUpdateMin
- );
- // Maximum update.
- $builder.on(
- 'input',
- '.wpforms-field-option-row-min_max .wpforms-input-row .wpforms-number-slider-max',
- app.fieldNumberSliderUpdateMax
- );
- // Change default input value.
- $builder.on(
- 'input',
- '.wpforms-number-slider-default-value',
- _.debounce( app.changeNumberSliderDefaultValue, 500 )
- );
- // Change step value.
- $builder.on(
- 'input',
- '.wpforms-number-slider-step',
- _.debounce( app.changeNumberSliderStep, 500 )
- );
- // Check step value.
- $builder.on(
- 'focusout',
- '.wpforms-number-slider-step',
- app.checkNumberSliderStep
- );
- // Change value display.
- $builder.on(
- 'input',
- '.wpforms-number-slider-value-display',
- _.debounce( app.changeNumberSliderValueDisplay, 500 )
- );
- // Change min value.
- $builder.on(
- 'input',
- '.wpforms-number-slider-min',
- _.debounce( app.changeNumberSliderMin, 500 )
- );
- // Change max value.
- $builder.on(
- 'input',
- '.wpforms-number-slider-max',
- _.debounce( app.changeNumberSliderMax, 500 )
- );
- },
- /**
- * Change number slider min option.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- changeNumberSliderMin: function( event ) {
- var fieldID = $( event.target ).parents( '.wpforms-field-option-row' ).data( 'fieldId' );
- var value = parseFloat( event.target.value );
- if ( isNaN( value ) ) {
- return;
- }
- app.updateNumberSliderDefaultValueAttr( fieldID, event.target.value, 'min' );
- },
- /**
- * Change number slider max option.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- changeNumberSliderMax: function( event ) {
- var fieldID = $( event.target ).parents( '.wpforms-field-option-row' ).data( 'fieldId' );
- var value = parseFloat( event.target.value );
- if ( isNaN( value ) ) {
- return;
- }
- app.updateNumberSliderDefaultValueAttr( fieldID, event.target.value, 'max' )
- .updateNumberSliderStepValueMaxAttr( fieldID, event.target.value );
- },
- /**
- * Change number slider value display option.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- changeNumberSliderValueDisplay: function( event ) {
- var str = event.target.value;
- var fieldID = $( event.target ).parents( '.wpforms-field-option-row' ).data( 'fieldId' );
- var defaultValue = document.getElementById( 'wpforms-field-option-' + fieldID + '-default_value' );
- if ( defaultValue ) {
- app.updateNumberSliderHintStr( fieldID, str )
- .updateNumberSliderHint( fieldID, defaultValue.value );
- }
- },
- /**
- * Change number slider step option.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- changeNumberSliderStep: function( event ) {
- var value = parseFloat( event.target.value );
- if ( isNaN( value ) ) {
- return;
- }
- var max = parseFloat( event.target.max );
- var min = parseFloat( event.target.min );
- var fieldID = $( event.target ).parents( '.wpforms-field-option-row' ).data( 'fieldId' );
- if ( value <= 0 ) {
- return;
- }
- if ( value > max ) {
- event.target.value = max;
- return;
- }
- if ( value < min ) {
- event.target.value = min;
- return;
- }
- app.updateNumberSliderAttr( fieldID, value, 'step' )
- .updateNumberSliderDefaultValueAttr( fieldID, value, 'step' );
- },
- /**
- * Check number slider step option.
- *
- * @since 1.6.2.3
- *
- * @param {object} event Focusout event object.
- */
- checkNumberSliderStep: function( event ) {
- var value = parseFloat( event.target.value ),
- $input = $( this );
- if ( ! isNaN( value ) && value > 0 ) {
- return;
- }
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.error_number_slider_increment,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- $input.val( '' ).focus();
- },
- },
- },
- } );
- },
- /**
- * Change number slider default value option.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- changeNumberSliderDefaultValue: function( event ) {
- var value = parseFloat( event.target.value );
- if ( ! isNaN( value ) ) {
- var max = parseFloat( event.target.max );
- var min = parseFloat( event.target.min );
- var fieldID = $( event.target ).parents( '.wpforms-field-option-row-default_value' ).data( 'fieldId' );
- if ( value > max ) {
- event.target.value = max;
- return;
- }
- if ( value < min ) {
- event.target.value = min;
- return;
- }
- app.updateNumberSlider( fieldID, value )
- .updateNumberSliderHint( fieldID, value );
- }
- },
- /**
- * Update number slider default value attribute.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {*} newValue Default value attribute.
- * @param {*} attr Attribute name.
- *
- * @returns {object} App instance.
- */
- updateNumberSliderDefaultValueAttr: function( fieldID, newValue, attr ) {
- var input = document.getElementById( 'wpforms-field-option-' + fieldID + '-default_value' );
- if ( input ) {
- var value = parseFloat( input.value );
- input.setAttribute( attr, newValue );
- newValue = parseFloat( newValue );
- if ( 'max' === attr && value > newValue ) {
- input.value = newValue;
- $( input ).trigger( 'input' );
- }
- if ( 'min' === attr && value < newValue ) {
- input.value = newValue;
- $( input ).trigger( 'input' );
- }
- }
- return this;
- },
- /**
- * Update number slider value.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {string} value Number slider value.
- *
- * @returns {object} App instance.
- */
- updateNumberSlider: function( fieldID, value ) {
- var numberSlider = document.getElementById( 'wpforms-number-slider-' + fieldID );
- if ( numberSlider ) {
- numberSlider.value = value;
- }
- return this;
- },
- /**
- * Update number slider attribute.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {mixed} value Attribute value.
- * @param {*} attr Attribute name.
- *
- * @returns {object} App instance.
- */
- updateNumberSliderAttr: function( fieldID, value, attr ) {
- var numberSlider = document.getElementById( 'wpforms-number-slider-' + fieldID );
- if ( numberSlider ) {
- numberSlider.setAttribute( attr, value );
- }
- return this;
- },
- /**
- * Update number slider hint string.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {string} str Hint string.
- *
- * @returns {object} App instance.
- */
- updateNumberSliderHintStr: function( fieldID, str ) {
- var hint = document.getElementById( 'wpforms-number-slider-hint-' + fieldID );
- if ( hint ) {
- hint.dataset.hint = str;
- }
- return this;
- },
- /**
- * Update number slider Hint value.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {string} value Hint value.
- *
- * @returns {object} App instance.
- */
- updateNumberSliderHint: function( fieldID, value ) {
- var hint = document.getElementById( 'wpforms-number-slider-hint-' + fieldID );
- if ( hint ) {
- hint.innerHTML = wpf.sanitizeHTML( hint.dataset.hint ).replace( '{value}', '<b>' + value + '</b>' );
- }
- return this;
- },
- /**
- * Update min attribute.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- fieldNumberSliderUpdateMin: function( event ) {
- var $options = $( event.target ).parents( '.wpforms-field-option-row-min_max' );
- var max = parseFloat( $options.find( '.wpforms-number-slider-max' ).val() );
- var current = parseFloat( event.target.value );
- if ( isNaN( current ) ) {
- return;
- }
- if ( max <= current ) {
- event.preventDefault();
- this.value = max;
- return;
- }
- var fieldId = $options.data( 'field-id' );
- var numberSlider = $builder.find( '#wpforms-field-' + fieldId + ' input[type="range"]' );
- numberSlider.attr( 'min', current );
- },
- /**
- * Update max attribute.
- *
- * @since 1.5.7
- *
- * @param {object} event Input event.
- */
- fieldNumberSliderUpdateMax: function( event ) {
- var $options = $( event.target ).parents( '.wpforms-field-option-row-min_max' );
- var min = parseFloat( $options.find( '.wpforms-number-slider-min' ).val() );
- var current = parseFloat( event.target.value );
- if ( isNaN( current ) ) {
- return;
- }
- if ( min >= current ) {
- event.preventDefault();
- this.value = min;
- return;
- }
- var fieldId = $options.data( 'field-id' );
- var numberSlider = $builder.find( '#wpforms-field-' + fieldId + ' input[type="range"]' );
- numberSlider.attr( 'max', current );
- },
- /**
- * Update max attribute for step value.
- *
- * @since 1.5.7
- *
- * @param {number} fieldID Field ID.
- * @param {*} newValue Default value attribute.
- *
- * @returns {object} App instance.
- */
- updateNumberSliderStepValueMaxAttr: function( fieldID, newValue ) {
- var input = document.getElementById( 'wpforms-field-option-' + fieldID + '-step' );
- if ( input ) {
- var value = parseFloat( input.value );
- input.setAttribute( 'max', newValue );
- newValue = parseFloat( newValue );
- if ( value > newValue ) {
- input.value = newValue;
- $( input ).trigger( 'input' );
- }
- }
- return this;
- },
- /**
- * Update upload selector.
- *
- * @since 1.5.6
- *
- * @param {object} target Changed :input.
- */
- fieldFileUploadPreviewUpdate: function( target ) {
- var $options = $( target ).parents( '.wpforms-field-option-file-upload' );
- var fieldId = $options.data( 'field-id' );
- var styleOption = $options.find( '#wpforms-field-option-' + fieldId + '-style' ).val();
- var $maxFileNumberRow = $options.find( '#wpforms-field-option-row-' + fieldId + '-max_file_number' );
- var maxFileNumber = parseInt( $maxFileNumberRow.find( 'input' ).val(), 10 );
- var $preview = $( '#wpforms-field-' + fieldId );
- var classicPreview = '.wpforms-file-upload-builder-classic';
- var modernPreview = '.wpforms-file-upload-builder-modern';
- if ( styleOption === 'classic' ) {
- $( classicPreview, $preview ).removeClass( 'wpforms-hide' );
- $( modernPreview, $preview ).addClass( 'wpforms-hide' );
- $maxFileNumberRow.addClass( 'wpforms-hidden' );
- } else {
- // Change hint and title.
- if ( maxFileNumber > 1 ) {
- $preview
- .find( '.modern-title' )
- .text( wpforms_builder.file_upload.preview_title_plural );
- $preview
- .find( '.modern-hint' )
- .text( wpforms_builder.file_upload.preview_hint.replace( '{maxFileNumber}', maxFileNumber ) )
- .removeClass( 'wpforms-hide' );
- } else {
- $preview
- .find( '.modern-title' )
- .text( wpforms_builder.file_upload.preview_title_single );
- $preview
- .find( '.modern-hint' )
- .text( wpforms_builder.file_upload.preview_hint.replace( '{maxFileNumber}', 1 ) )
- .addClass( 'wpforms-hide' );
- }
- // Display the preview.
- $( classicPreview, $preview ).addClass( 'wpforms-hide' );
- $( modernPreview, $preview ).removeClass( 'wpforms-hide' );
- $maxFileNumberRow.removeClass( 'wpforms-hidden' );
- }
- },
- /**
- * Update limit controls by changing checkbox.
- *
- * @since 1.5.6
- *
- * @param {number} id Field id.
- * @param {bool} checked Whether an option is checked or not.
- */
- updateTextFieldsLimitControls: function( id, checked ) {
- if ( ! checked ) {
- $( '#wpforms-field-option-row-' + id + '-limit_controls' ).addClass( 'wpforms-hide' );
- } else {
- $( '#wpforms-field-option-row-' + id + '-limit_controls' ).removeClass( 'wpforms-hide' );
- }
- },
- /**
- * Update Password Strength controls by changing checkbox.
- *
- * @since 1.6.7
- *
- * @param {number} id Field id.
- * @param {bool} checked Whether an option is checked or not.
- */
- updatePasswordStrengthControls: function( id, checked ) {
- var $strengthControls = $( '#wpforms-field-option-row-' + id + '-password-strength-level' );
- if ( checked ) {
- $strengthControls.removeClass( 'wpforms-hidden' );
- } else {
- $strengthControls.addClass( 'wpforms-hidden' );
- }
- },
- /**
- * Update Rich Text media controls by changing checkbox.
- *
- * @since 1.7.0
- */
- updateRichTextMediaFieldsLimitControls: function() {
- var $this = $( this ),
- fieldId = $this.closest( '.wpforms-field-option-row-media_enabled' ).data( 'field-id' ),
- $mediaControls = $( '#wpforms-field-option-row-' + fieldId + '-media_controls' ),
- $toolbar = $( '#wpforms-field-' + fieldId + ' .wpforms-richtext-wrap .mce-toolbar-grp' );
- if ( ! $this.is( ':checked' ) ) {
- $mediaControls.hide();
- $toolbar.removeClass( 'wpforms-field-richtext-media-enabled' );
- } else {
- $mediaControls.show();
- $toolbar.addClass( 'wpforms-field-richtext-media-enabled' );
- }
- },
- /**
- * Update Rich Text style preview by changing select.
- *
- * @since 1.7.0
- */
- updateRichTextStylePreview: function() {
- var $this = $( this ),
- fieldId = $this.closest( '.wpforms-field-option-row-style' ).data( 'field-id' ),
- $toolbar = $( '#wpforms-field-' + fieldId + ' .wpforms-richtext-wrap .mce-toolbar-grp' );
- $toolbar.toggleClass( 'wpforms-field-richtext-toolbar-basic', $this.val() !== 'full' );
- },
- /**
- * Element bindings.
- *
- * @since 1.0.0
- */
- bindUIActions: function() {
- // General Panels.
- app.bindUIActionsPanels();
- // Fields Panel.
- app.bindUIActionsFields();
- // Settings Panel.
- app.bindUIActionsSettings();
- // Save and Exit.
- app.bindUIActionsSaveExit();
- // General/ global.
- app.bindUIActionsGeneral();
- },
- //--------------------------------------------------------------------//
- // General Panels
- //--------------------------------------------------------------------//
- /**
- * Element bindings for general panel tasks.
- *
- * @since 1.0.0
- */
- bindUIActionsPanels: function() {
- // Panel switching.
- $builder.on('click', '#wpforms-panels-toggle button, .wpforms-panel-switch', function(e) {
- e.preventDefault();
- app.panelSwitch($(this).data('panel'));
- });
- // Panel sections switching.
- $builder.on('click', '.wpforms-panel .wpforms-panel-sidebar-section', function(e) {
- app.panelSectionSwitch(this, e);
- });
- },
- /**
- * Switch Panels.
- *
- * @since 1.0.0
- * @since 1.5.9 Added `wpformsPanelSwitched` triger.
- *
- * @param {string} panel Panel slug.
- *
- * @returns {mixed} Void or false.
- */
- panelSwitch: function( panel ) {
- var $panel = $( '#wpforms-panel-' + panel ),
- $panelBtn = $( '.wpforms-panel-' + panel + '-button' );
- if ( ! $panel.hasClass( 'active' ) ) {
- $builder.trigger( 'wpformsPanelSwitch', [ panel ] );
- if ( ! wpforms_panel_switch ) {
- return false;
- }
- $( '#wpforms-panels-toggle' ).find( 'button' ).removeClass( 'active' );
- $( '.wpforms-panel' ).removeClass( 'active' );
- $panelBtn.addClass( 'active' );
- $panel.addClass( 'active' );
- history.replaceState( {}, null, wpf.updateQueryString( 'view', panel ) );
- $builder.trigger( 'wpformsPanelSwitched', [ panel ] );
- }
- },
- /**
- * Switch Panel section.
- *
- * @since 1.0.0
- */
- panelSectionSwitch: function(el, e) {
- if (e) {
- e.preventDefault();
- }
- var $this = $(el),
- $panel = $this.parent().parent(),
- section = $this.data('section'),
- $sectionButtons = $panel.find('.wpforms-panel-sidebar-section'),
- $sectionButton = $panel.find('.wpforms-panel-sidebar-section-'+section);
- if ( $this.hasClass( 'upgrade-modal' ) || $this.hasClass( 'education-modal' ) ) {
- return;
- }
- if ( ! $sectionButton.hasClass('active') ) {
- $builder.trigger('wpformsPanelSectionSwitch', section);
- $sectionButtons.removeClass('active');
- $sectionButton.addClass('active');
- $panel.find('.wpforms-panel-content-section').hide();
- $panel.find('.wpforms-panel-content-section-'+section).show();
- }
- },
- //--------------------------------------------------------------------//
- // Setup Panel
- //--------------------------------------------------------------------//
- /**
- * Element bindings for Setup panel.
- *
- * @since 1.0.0
- * @since 1.6.8 Deprecated.
- *
- * @deprecated Use `WPForms.Admin.Builder.Setup.events()` instead.
- */
- bindUIActionsSetup: function() {
- console.warn( 'WARNING! Function "WPFormsBuilder.bindUIActionsSetup()" has been deprecated, please use the new "WPForms.Admin.Builder.Setup.events()" function instead!' );
- WPForms.Admin.Builder.Setup.events();
- },
- /**
- * Select template.
- *
- * @since 1.0.0
- * @since 1.6.8 Deprecated.
- *
- * @deprecated Use `WPForms.Admin.Builder.Setup.selectTemplate()` instead.
- *
- * @param {object} el DOM element object.
- * @param {object} e Event object.
- */
- templateSelect: function( el, e ) {
- console.warn( 'WARNING! Function "WPFormsBuilder.templateSelect()" has been deprecated, please use the new "WPForms.Admin.Builder.Setup.selectTemplate()" function instead!' );
- WPForms.Admin.Builder.Setup.selectTemplate( e );
- },
- //--------------------------------------------------------------------//
- // Fields Panel
- //--------------------------------------------------------------------//
- /**
- * Element bindings for Fields panel.
- *
- * @since 1.0.0
- */
- bindUIActionsFields: function() {
- // Field sidebar tab toggle
- $builder.on('click', '.wpforms-tab a', function(e) {
- e.preventDefault();
- app.fieldTabToggle($(this).parent().attr('id'));
- });
- // Field sidebar group toggle
- $builder.on('click', '.wpforms-add-fields-heading', function(e) {
- e.preventDefault();
- app.fieldGroupToggle($(this), 'click');
- });
- // Form field preview clicking.
- $builder.on( 'click', '.wpforms-field', function( e ) {
- if ( app.isFieldPreviewActionsDisabled( this ) ) {
- return;
- }
- app.fieldTabToggle( $( this ).data( 'field-id' ) );
- } );
- // Prevent interactions with inputs on the preview panel.
- $builder.on( 'mousedown click', '.wpforms-field input, .wpforms-field select, .wpforms-field textarea', function( e ) {
- e.preventDefault();
- this.blur();
- } );
- // Field delete.
- $builder.on( 'click', '.wpforms-field-delete', function( e ) {
- e.preventDefault();
- e.stopPropagation();
- if ( app.isFieldPreviewActionsDisabled( this ) ) {
- return;
- }
- app.fieldDelete( $( this ).parent().data( 'field-id' ) );
- } );
- // Field duplicate.
- $builder.on( 'click', '.wpforms-field-duplicate', function( e ) {
- e.preventDefault();
- e.stopPropagation();
- if ( app.isFieldPreviewActionsDisabled( this ) ) {
- return;
- }
- app.fieldDuplicate( $( this ).parent().data( 'field-id' ) );
- } );
- // Field add
- $builder.on( 'click', '.wpforms-add-fields-button', function( e ) {
- e.preventDefault();
- var $field = $( this );
- if ( $field.hasClass( 'ui-draggable-disabled' ) ) {
- return;
- }
- app.fieldAdd( $field.data( 'field-type' ) );
- } );
- // New field choices should be sortable
- $builder.on('wpformsFieldAdd', function(event, id, type) {
- if (type === 'select' || type === 'radio' || type === 'checkbox' || type === 'payment-multiple' || type === 'payment-checkbox' || type === 'payment-select' ) {
- app.fieldChoiceSortable(type,'#wpforms-field-option-row-' + id + '-choices ul');
- }
- });
- // Field choice add new
- $builder.on('click', '.wpforms-field-option-row-choices .add', function(e) {
- app.fieldChoiceAdd(e, $(this));
- });
- // Field choice delete
- $builder.on('click', '.wpforms-field-option-row-choices .remove', function(e) {
- app.fieldChoiceDelete(e, $(this));
- });
- // Field choices defaults - before change
- $builder.on('mousedown', '.wpforms-field-option-row-choices input[type=radio]', function(e) {
- var $this = $(this);
- if ( $this.is(':checked') ) {
- $this.attr('data-checked', '1');
- } else {
- $this.attr('data-checked', '0');
- }
- });
- // Field choices defaults
- $builder.on('click', '.wpforms-field-option-row-choices input[type=radio]', function(e) {
- var $this = $(this),
- list = $this.parent().parent();
- $this.parent().parent().find('input[type=radio]').not(this).prop('checked',false);
- if ( $this.attr('data-checked') === '1' ) {
- $this.prop( 'checked', false );
- $this.attr('data-checked', '0');
- }
- app.fieldChoiceUpdate(list.data('field-type'),list.data('field-id') );
- });
- // Field choices update preview area
- $builder.on( 'change', '.wpforms-field-option-row-choices input[type=checkbox]', function( e ) {
- var list = $( this ).parent().parent();
- app.fieldChoiceUpdate( list.data( 'field-type' ), list.data( 'field-id' ) );
- } );
- // Field choices display value toggle
- $builder.on('change', '.wpforms-field-option-row-show_values input', function(e) {
- $(this).closest('.wpforms-field-option').find('.wpforms-field-option-row-choices ul').toggleClass('show-values');
- });
- // Field choices image toggle.
- $builder.on( 'change', '.wpforms-field-option-row-choices_images input', function() {
- var $this = $( this ),
- $optionRow = $this.closest( '.wpforms-field-option-row' ),
- fieldID = $optionRow.data( 'field-id' ),
- $fieldOptions = $( '#wpforms-field-option-' + fieldID ),
- checked = $this.is( ':checked' ),
- type = $fieldOptions.find( '.wpforms-field-option-hidden-type' ).val();
- $optionRow.find( '.wpforms-alert' ).toggleClass( 'wpforms-hidden' );
- $fieldOptions.find( '.wpforms-field-option-row-choices ul' ).toggleClass( 'show-images' );
- $fieldOptions.find( '.wpforms-field-option-row-choices_images_style' ).toggleClass( 'wpforms-hidden' );
- if ( checked ) {
- $( '#wpforms-field-option-' + fieldID + '-input_columns' ).val( 'inline' ).trigger( 'change' );
- } else {
- $( '#wpforms-field-option-' + fieldID + '-input_columns' ).val( '' ).trigger( 'change' );
- }
- app.fieldChoiceUpdate( type, fieldID );
- } );
- // Field choices image upload add/remove image.
- $builder.on( 'wpformsImageUploadAdd wpformsImageUploadRemove', function( event, $this, $container ) {
- var $list = $container.closest( '.choices-list' ),
- fieldID = $list.data( 'field-id' ),
- type = $list.data( 'field-type' );
- app.fieldChoiceUpdate( type, fieldID );
- } );
- // Field choices image style toggle.
- $builder.on( 'change', '.wpforms-field-option-row-choices_images_style select', function() {
- var fieldID = $( this ).parent().data( 'field-id' ),
- type = $( '#wpforms-field-option-'+fieldID ).find( '.wpforms-field-option-hidden-type' ).val();
- app.fieldChoiceUpdate( type, fieldID );
- } );
- // Updates field choices text in almost real time.
- $builder.on( 'keyup', '.wpforms-field-option-row-choices input.label, .wpforms-field-option-row-choices input.value', function( e ) {
- var $list = $( this ).parent().parent();
- app.fieldChoiceUpdate( $list.data( 'field-type' ), $list.data( 'field-id' ) );
- } );
- // Field Choices Bulk Add
- $builder.on('click', '.toggle-bulk-add-display', function(e) {
- e.preventDefault();
- app.fieldChoiceBulkAddToggle(this);
- });
- $builder.on('click', '.toggle-bulk-add-presets', function(e) {
- e.preventDefault();
- var $presetList = $(this).closest('.bulk-add-display').find('ul');
- if ( $presetList.css('display') === 'block' ) {
- $(this).text(wpforms_builder.bulk_add_presets_show);
- } else {
- $(this).text(wpforms_builder.bulk_add_presets_hide);
- }
- $presetList.stop().slideToggle();
- });
- $builder.on('click', '.bulk-add-preset-insert', function(e) {
- e.preventDefault();
- var $this = $(this),
- preset = $this.data('preset'),
- $container = $this.closest('.bulk-add-display'),
- $presetList = $container.find('ul'),
- $presetToggle = $container.find('.toggle-bulk-add-presets'),
- $textarea = $container.find('textarea');
- $textarea.val('');
- $textarea.insertAtCaret(wpforms_preset_choices[preset].choices.join("\n"));
- $presetToggle.text(wpforms_builder.bulk_add_presets_show);
- $presetList.slideUp();
- });
- $builder.on('click', '.bulk-add-insert', function(e) {
- e.preventDefault();
- app.fieldChoiceBulkAddInsert(this);
- });
- // Field Options group tabs.
- $builder.on( 'click', '.wpforms-field-option-group-toggle:not(.education-modal)', function( e ) {
- e.preventDefault();
- var $group = $( this ).closest( '.wpforms-field-option-group' );
- $group.siblings( '.wpforms-field-option-group' ).removeClass( 'active' );
- $group.addClass( 'active' );
- } );
- // Display toggle for Address field hide address line 2 option.
- $builder.on( 'change', '.wpforms-field-option-address input.wpforms-subfield-hide', function( e ) {
- var $optionRow = $( this ).closest( '.wpforms-field-option-row' ),
- id = $optionRow.data( 'field-id' ),
- subfield = $optionRow.data( 'subfield' );
- $( '#wpforms-field-' + id ).find( '.wpforms-' + subfield ).toggleClass( 'wpforms-hide' );
- } );
- // Real-time updates for "Show Label" field option
- $builder.on( 'input', '.wpforms-field-option-row-label input, .wpforms-field-option-row-name input', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' ),
- $preview = $( '#wpforms-field-' + id ),
- type = $preview.data( 'field-type' ),
- showClass = value.length === 0;
- // Do not modify label of the HTML field.
- if ( type === 'html' ) {
- showClass = false;
- }
- if ( showClass ) {
- value = wpforms_builder.empty_label;
- }
- $preview.toggleClass( 'label_empty', showClass ).find( '.label-title .text' ).text( value );
- } );
- // Real-time updates for "Description" field option
- $builder.on( 'input', '.wpforms-field-option-row-description textarea', function() {
- var $this = $( this ),
- value = wpf.sanitizeHTML( $this.val() ),
- id = $this.parent().data( 'field-id' ),
- $desc = $( '#wpforms-field-'+id ).find( '.description' );
- app.updateDescription( $desc, value );
- });
- // Real-time updates for "Required" field option
- $builder.on( 'change', '.wpforms-field-option-row-required input', function( e ) {
- var id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' );
- $( '#wpforms-field-' + id ).toggleClass( 'required' );
- } );
- // Real-time updates for "Confirmation" field option
- $builder.on( 'change', '.wpforms-field-option-row-confirmation input', function( e ) {
- var id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' );
- $( '#wpforms-field-' + id ).find( '.wpforms-confirm' ).toggleClass( 'wpforms-confirm-enabled wpforms-confirm-disabled' );
- $( '#wpforms-field-option-' + id ).toggleClass( 'wpforms-confirm-enabled wpforms-confirm-disabled' );
- } );
- // Real-time updates for "Filter" field option
- $builder.on( 'change', '.wpforms-field-option-row-filter_type select', function() {
- var id = $( this ).parent().data( 'field-id' ),
- $toggledField = $( '#wpforms-field-option-' + id );
- if ( $( this ).val() ) {
- $toggledField.removeClass( 'wpforms-filter-allowlist' );
- $toggledField.removeClass( 'wpforms-filter-denylist' );
- $toggledField.addClass( 'wpforms-filter-' + $( this ).val() );
- } else {
- $toggledField.removeClass( 'wpforms-filter-allowlist' );
- $toggledField.removeClass( 'wpforms-filter-denylist' );
- }
- } );
- $builder.on( 'focusout', '.wpforms-field-option-row-allowlist textarea,.wpforms-field-option-row-denylist textarea', function() {
- var $field = $( this );
- $.get(
- wpforms_builder.ajax_url,
- {
- nonce: wpforms_builder.nonce,
- content: $field.val(),
- action: 'wpforms_sanitize_restricted_rules',
- },
- function( res ) {
- if ( res.success ) {
- $field.val( res.data );
- }
- }
- );
- } );
- // Real-time updates for "Size" field option
- $builder.on('change', '.wpforms-field-option-row-size select', function(e) {
- var $this = $(this),
- value = $this.val(),
- id = $this.parent().data('field-id');
- $('#wpforms-field-'+id).removeClass('size-small size-medium size-large').addClass('size-'+value);
- });
- // Real-time updates for "Placeholder" field option.
- $builder.on( 'input', '.wpforms-field-option-row-placeholder input', function() {
- var $this = $( this ),
- value = wpf.sanitizeHTML( $this.val() ),
- id = $this.parent().data( 'field-id' ),
- $primary = $( '#wpforms-field-' + id + ' .primary-input' );
- // Set the placeholder value for `input` fields.
- if ( ! $primary.is( 'select' ) ) {
- $primary.prop( 'placeholder', value );
- return;
- }
- // Modern select style.
- if ( app.dropdownField.helpers.isModernSelect( $primary ) ) {
- var choicejsInstance = app.dropdownField.helpers.getInstance( $primary );
- // Additional case for multiple select.
- if ( $primary.prop( 'multiple' ) ) {
- $( choicejsInstance.input.element ).prop( 'placeholder', value );
- } else {
- choicejsInstance.setChoiceByValue( '' );
- $primary.closest( '.choices' ).find( '.choices__inner .choices__placeholder' ).text( value );
- var isDynamicChoices = $( '#wpforms-field-option-' + id + '-dynamic_choices' ).val();
- // We need to re-initialize modern dropdown to properly determine and update placeholder.
- app.dropdownField.helpers.update( id, isDynamicChoices );
- }
- return;
- }
- var $placeholder = $primary.find( '.placeholder' );
- // Classic select style.
- if ( ! value.length && $placeholder.length ) {
- $placeholder.remove();
- } else {
- if ( $placeholder.length ) {
- $placeholder.text( value );
- } else {
- $primary.prepend( '<option value="" class="placeholder">' + value + '</option>' );
- }
- $primary.find( '.placeholder' ).prop( 'selected', ! $primary.prop( 'multiple' ) );
- }
- } );
- // Real-time updates for "Confirmation Placeholder" field option
- $builder.on('input', '.wpforms-field-option-row-confirmation_placeholder input', function(e) {
- var $this = $(this),
- value = $this.val(),
- id = $this.parent().data('field-id');
- $('#wpforms-field-'+id).find('.secondary-input').attr('placeholder', value);
- });
- // Real-time updates for "Hide Label" field option.
- $builder.on( 'change', '.wpforms-field-option-row-label_hide input', function( e ) {
- var id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' );
- $( '#wpforms-field-' + id ).toggleClass( 'label_hide' );
- } );
- // Real-time updates for Sub Label visbility field option.
- $builder.on( 'change', '.wpforms-field-option-row-sublabel_hide input', function( e ) {
- var id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' );
- $( '#wpforms-field-' + id ).toggleClass( 'sublabel_hide' );
- } );
- // Real-time updates for Date/Time and Name "Format" option
- $builder.on('change', '.wpforms-field-option-row-format select', function(e) {
- var $this = $(this),
- value = $this.val(),
- id = $this.parent().data('field-id');
- $('#wpforms-field-'+id).find('.format-selected').removeClass().addClass('format-selected format-selected-'+value);
- $('#wpforms-field-option-'+id).find('.format-selected').removeClass().addClass('format-selected format-selected-'+value);
- });
- // Real-time updates specific for Address "Scheme" option
- $builder.on('change', '.wpforms-field-option-row-scheme select', function(e) {
- var $this = $(this),
- value = $this.val(),
- id = $this.parent().data('field-id'),
- $field = $('#wpforms-field-'+id);
- $field.find('.wpforms-address-scheme').addClass('wpforms-hide');
- $field.find('.wpforms-address-scheme-'+value).removeClass('wpforms-hide');
- if ( $field.find('.wpforms-address-scheme-'+value+' .wpforms-country' ).children().length == 0 ) {
- $('#wpforms-field-option-'+id).find('.wpforms-field-option-row-country').addClass('wpforms-hidden');
- } else {
- $('#wpforms-field-option-'+id).find('.wpforms-field-option-row-country').removeClass('wpforms-hidden');
- }
- });
- // Real-time updates for Address, Date/Time, and Name "Placeholder" field options
- $builder.on( 'input', '.wpforms-field-option .format-selected input.placeholder, .wpforms-field-option-address input.placeholder', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- $fieldOptionRow = $this.closest( '.wpforms-field-option-row' ),
- id = $fieldOptionRow.data( 'field-id' ),
- subfield = $fieldOptionRow.data( 'subfield' );
- $( '#wpforms-field-' + id ).find( '.wpforms-' + subfield + ' input' ).attr( 'placeholder', value );
- } );
- // Real-time updates for Date/Time date type
- $builder.on( 'change', '.wpforms-field-option-row-date .type select', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' ),
- addClass = value === 'datepicker' ? 'wpforms-date-type-datepicker' : 'wpforms-date-type-dropdown',
- removeClass = value === 'datepicker' ? 'wpforms-date-type-dropdown' : 'wpforms-date-type-datepicker';
- $( '#wpforms-field-' + id ).find( '.wpforms-date' ).addClass( addClass ).removeClass( removeClass );
- $( '#wpforms-field-option-' + id ).addClass( addClass ).removeClass( removeClass );
- var $limitDays = $this.closest( '.wpforms-field-option-group-advanced' )
- .find( '.wpforms-field-option-row-date_limit_days, .wpforms-field-option-row-date_limit_days_options, .wpforms-field-option-row-date_disable_past_dates' ),
- $limitDaysOptions = $( '#wpforms-field-option-row-' + id + '-date_limit_days_options' );
- if ( value === 'dropdown' ) {
- var $dateSelect = $( '#wpforms-field-option-' + id + '-date_format' );
- if ( $dateSelect.find( 'option:selected' ).hasClass( 'datepicker-only' ) ) {
- $dateSelect.prop( 'selectedIndex', 0 ).trigger( 'change' );
- }
- $limitDays.hide();
- } else {
- $limitDays.show();
- $( '#wpforms-field-option-' + id + '-date_limit_days' ).is( ':checked' ) ?
- $limitDaysOptions.show() : $limitDaysOptions.hide();
- }
- } );
- // Real-time updates for Date/Time date select format
- $builder.on( 'change', '.wpforms-field-option-row-date .format select', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' ),
- $field = $( '#wpforms-field-' + id );
- if ( value === 'm/d/Y' ) {
- $field.find( '.wpforms-date-dropdown .first option' ).text( wpforms_builder.date_select_month );
- $field.find( '.wpforms-date-dropdown .second option' ).text( wpforms_builder.date_select_day );
- } else if ( value === 'd/m/Y' ) {
- $field.find( '.wpforms-date-dropdown .first option' ).text( wpforms_builder.date_select_day );
- $field.find( '.wpforms-date-dropdown .second option' ).text( wpforms_builder.date_select_month );
- }
- } );
- // Real-time updates for Date/Time time select format
- $builder.on( 'change', '.wpforms-field-option-row-time .format select', function( e ) {
- var $this = $( this ),
- id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' ),
- options = '',
- hh;
- // Determine time format type.
- // If the format contains `g` or `h`, then this is 12 hours format, otherwise 24 hours.
- var format = $this.val().match( /[gh]/ ) ? 12 : 24;
- // Generate new set of hours options.
- for ( var i = 0; i < format; i++ ) {
- hh = i < 10 ? '0' + i : i;
- options += '<option value="{hh}">{hh}</option>'.replace( /{hh}/g, hh );
- }
- _.forEach( [ 'start', 'end' ], function( field ) {
- var $hour = $builder.find( '#wpforms-field-option-' + id + '-time_limit_hours_' + field + '_hour' ),
- $ampm = $builder.find( '#wpforms-field-option-' + id + '-time_limit_hours_' + field + '_ampm' ),
- hourValue = parseInt( $hour.val(), 10 ),
- ampmValue = $ampm.val();
- if ( format === 24 ) {
- hourValue = ampmValue === 'pm' ? hourValue + 12 : hourValue;
- } else {
- ampmValue = hourValue > 12 ? 'pm' : 'am';
- hourValue = hourValue > 12 ? hourValue - 12 : hourValue;
- }
- hourValue = hourValue < 10 ? '0' + hourValue : hourValue;
- $hour.html( options ).val( hourValue );
- $ampm.toggleClass( 'wpforms-hidden-strict', format === 24 ).val( ampmValue );
- $ampm.nextAll( 'div' ).toggleClass( 'wpforms-hidden-strict', format === 12 );
- } );
- } );
- // Consider the field active when a disabled nav button is clicked
- $builder.on('click', '.wpforms-pagebreak-button', function(e) {
- e.preventDefault();
- $(this).closest('.wpforms-field').trigger('click');
- });
- /*
- * Pagebreak field.
- */
- app.fieldPageBreakInitDisplayPrevious( $builder.find( '.wpforms-field-pagebreak.wpforms-pagebreak-normal:first' ) );
- $builder
- .on( 'input', '.wpforms-field-option-row-next input', function( e ) {
- // Real-time updates for "Next" pagebreak field option.
- var $this = $( this ),
- value = $this.val(),
- $next = $( '#wpforms-field-' + $this.parent().data( 'field-id' ) ).find( '.wpforms-pagebreak-next' );
- if ( value ) {
- $next.css( 'display', 'inline-block' ).text( value );
- } else {
- $next.css( 'display', 'none' ).empty();
- }
- } )
- .on( 'input', '.wpforms-field-option-row-prev input', function( e ) {
- // Real-time updates for "Prev" pagebreak field option.
- var $this = $( this ),
- value = $this.val().trim(),
- $field = $( '#wpforms-field-' + $this.parent().data( 'field-id' ) ),
- $prevBtn = $field.find( '.wpforms-pagebreak-prev' );
- if ( value && $field.prevAll( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).length > 0 ) {
- $prevBtn.removeClass( 'wpforms-hidden' ).text( value );
- } else {
- $prevBtn.addClass( 'wpforms-hidden' ).empty();
- }
- } )
- .on( 'change', '.wpforms-field-option-row-prev_toggle input', function( e ) {
- // Real-time updates for "Display Previous" pagebreak field option.
- var $input = $( this ),
- $wrapper = $input.closest( '.wpforms-field-option-row-prev_toggle' ),
- $prev = $input.closest( '.wpforms-field-option-group-inner' ).find( '.wpforms-field-option-row-prev' ),
- $prevLabel = $prev.find( 'input' ),
- $prevBtn = $( '#wpforms-field-' + $input.closest( '.wpforms-field-option' ).data( 'field-id' ) ).find( '.wpforms-pagebreak-prev' );
- if ( $wrapper.hasClass( 'wpforms-entry-preview-block' ) ) {
- return;
- }
- $prev.toggleClass( 'wpforms-hidden', ! $input.prop( 'checked' ) );
- $prevBtn.toggleClass( 'wpforms-hidden', ! $input.prop( 'checked' ) );
- if ( $input.prop( 'checked' ) && ! $prevLabel.val() ) {
- var message = $prevLabel.data( 'last-value' );
- message = message && message.trim() ? message.trim() : wpforms_builder.previous;
- $prevLabel.val( message );
- }
- // Backward compatibility for forms that were created before the toggle was added.
- if ( ! $input.prop( 'checked' ) ) {
- $prevLabel.data( 'last-value', $prevLabel.val() );
- $prevLabel.val( '' );
- }
- $prevLabel.trigger( 'input' );
- } )
- .on( 'wpformsFieldAdd', app.fieldPagebreakAdd )
- .on( 'wpformsFieldDelete', app.fieldPagebreakDelete )
- .on( 'wpformsBeforeFieldDelete', app.fieldEntryPreviewDelete );
- // Update Display Previous option visibility for all Pagebreak fields.
- $builder.on( 'wpformsFieldMove wpformsFieldAdd wpformsFieldDelete', function( e ) {
- $builder.find( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).each( function( i ) {
- app.fieldPageBreakInitDisplayPrevious( $( this ) );
- } );
- } );
- // Real-time updates for "Page Title" pagebreak field option
- $builder.on( 'input', '.wpforms-field-option-row-title input', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' );
- if ( value ) {
- $( '#wpforms-field-' + id ).find( '.wpforms-pagebreak-title' ).text( '(' + value + ')' );
- } else {
- $( '#wpforms-field-' + id ).find( '.wpforms-pagebreak-title' ).empty();
- }
- } );
- // Real-time updates for "Page Navigation Alignment" pagebreak field option
- $builder.on( 'change', '.wpforms-field-option-row-nav_align select', function( e ) {
- var $this = $( this ),
- value = $this.val();
- if ( ! value ) {
- value = 'center';
- }
- $( '.wpforms-pagebreak-buttons' )
- .removeClass( 'wpforms-pagebreak-buttons-center wpforms-pagebreak-buttons-left wpforms-pagebreak-buttons-right wpforms-pagebreak-buttons-split' )
- .addClass( 'wpforms-pagebreak-buttons-' + value );
- } );
- // Real-time updates for Single Item field "Item Price" option.
- $builder.on( 'input', '.wpforms-field-option-row-price input', function( e ) {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' ),
- sanitized = wpf.amountSanitize( value ),
- formatted = wpf.amountFormat( sanitized ),
- singleItem;
- if ( wpforms_builder.currency_symbol_pos === 'right' ) {
- singleItem = formatted + ' ' + wpforms_builder.currency_symbol;
- } else {
- singleItem = wpforms_builder.currency_symbol + ' ' + formatted;
- }
- $( '#wpforms-field-' + id ).find( '.primary-input' ).val( formatted );
- $( '#wpforms-field-' + id ).find( '.price' ).text( singleItem );
- } );
- // Real-time updates for payment CC icons
- $builder.on( 'change', '.wpforms-field-option-credit-card .payment-icons input', function( e ) {
- var $this = $( this ),
- card = $this.data( 'card' ),
- id = $this.parent().data( 'field-id' );
- $( '#wpforms-field-' + id ).find( 'img.icon-' + card ).toggleClass( 'card_hide' );
- } );
- // Generic updates for various additional placeholder fields
- $builder.on('input', '.wpforms-field-option input.placeholder-update', function(e) {
- var $this = $(this),
- value = $this.val(),
- id = $this.data('field-id'),
- subfield = $this.data('subfield');
- $('#wpforms-field-'+id).find('.wpforms-'+ subfield+' input' ).attr('placeholder', value);
- });
- // Toggle Choice Layout advanced field option.
- $builder.on( 'change', '.wpforms-field-option-row-input_columns select', function() {
- var $this = $( this ),
- value = $this.val(),
- cls = '',
- id = $this.parent().data( 'field-id' );
- if ( value === '2' ) {
- cls = 'wpforms-list-2-columns';
- } else if ( value === '3' ) {
- cls = 'wpforms-list-3-columns';
- } else if ( value === 'inline' ) {
- cls = 'wpforms-list-inline';
- }
- $( '#wpforms-field-' + id ).removeClass( 'wpforms-list-2-columns wpforms-list-3-columns wpforms-list-inline' ).addClass( cls );
- });
- // Toggle the toggle field.
- $builder.on( 'change', '.wpforms-field-option-row .wpforms-toggle-control input', function( e ) {
- var $check = $( this ),
- $control = $check.closest( '.wpforms-toggle-control' ),
- $status = $control.find( '.wpforms-toggle-control-status' ),
- state = $check.is( ':checked' ) ? 'on' : 'off';
- $status.html( $status.data( state ) );
- } );
- // Real-time updates for "Dynamic Choices" field option, for Dropdown,
- // Checkboxes, and Multiple choice fields
- $builder.on('change', '.wpforms-field-option-row-dynamic_choices select', function(e) {
- app.fieldDynamicChoiceToggle($(this));
- });
- // Real-time updates for "Dynamic [type] Source" field option, for Dropdown,
- // Checkboxes, and Multiple choice fields
- $builder.on('change', '.wpforms-field-option-row-dynamic_taxonomy select, .wpforms-field-option-row-dynamic_post_type select', function(e) {
- app.fieldDynamicChoiceSource($(this));
- });
- // Toggle Layout selector
- $builder.on('click', '.toggle-layout-selector-display', function(e) {
- e.preventDefault();
- app.fieldLayoutSelectorToggle(this);
- });
- $builder.on('click', '.layout-selector-display-layout', function(e) {
- e.preventDefault();
- app.fieldLayoutSelectorLayout(this);
- });
- $builder.on('click', '.layout-selector-display-columns span', function(e) {
- e.preventDefault();
- app.fieldLayoutSelectorInsert(this);
- });
- // Real-time updates for Rating field scale option.
- $( document ).on( 'change', '.wpforms-field-option-row-scale select', function() {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' ),
- $icons = $( '#wpforms-field-'+id +' .rating-icon' ),
- x = 1;
- $icons.each( function( index ) {
- if ( x <= value ) {
- $( this ).show();
- } else {
- $( this ).hide();
- }
- x++;
- });
- });
- // Real-time updates for Rating field icon option.
- $( document ).on( 'change', '.wpforms-field-option-row-icon select', function() {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' ),
- $icons = $( '#wpforms-field-'+id +' .rating-icon' ),
- iconClass = 'fa-star';
- if ( 'heart' === value ) {
- iconClass = 'fa-heart';
- } else if ( 'thumb' === value ) {
- iconClass = 'fa-thumbs-up';
- } else if ( 'smiley' === value ) {
- iconClass = 'fa-smile-o';
- }
- $icons.removeClass( 'fa-star fa-heart fa-thumbs-up fa-smile-o' ).addClass( iconClass );
- });
- // Real-time updates for Rating field icon size option.
- $( document ).on( 'change', '.wpforms-field-option-row-icon_size select', function() {
- var $this = $( this ),
- value = $this.val(),
- id = $this.parent().data( 'field-id' ),
- $icons = $( '#wpforms-field-'+id +' .rating-icon' );
- fontSize = '28';
- if ( 'small' === value ) {
- fontSize = '18';
- } else if ( 'large' === value ) {
- fontSize = '38';
- }
- $icons.css( 'font-size', fontSize + 'px' );
- });
- // Real-time updates for Rating field icon color option.
- $( document ).on( 'input', '.wpforms-field-option-row-icon_color input.wpforms-color-picker', function() {
- var $this = $( this ),
- value = $this.val(),
- id = $this.closest( '.wpforms-field-option-row' ).data( 'field-id' ),
- $icons = $( '#wpforms-field-' + id + ' > i.fa' );
- $icons.css( 'color', value );
- } );
- // Real-time updates for Checkbox field Disclaimer option.
- $( document ).on( 'change', '.wpforms-field-option-row-disclaimer_format input', function() {
- var $this = $( this ),
- id = $this.closest( '.wpforms-field-option-row' ).data( 'field-id' ),
- $desc = $( '#wpforms-field-' + id + ' .description' );
- $desc.toggleClass( 'disclaimer' );
- } );
- $builder.on(
- 'change',
- '.wpforms-field-option-row-limit_enabled input',
- function( event ) {
- app.updateTextFieldsLimitControls( $( event.target ).closest( '.wpforms-field-option-row-limit_enabled' ).data().fieldId, event.target.checked );
- }
- );
- $builder.on(
- 'change',
- '.wpforms-field-option-row-password-strength input',
- function( event ) {
- app.updatePasswordStrengthControls( $( event.target ).parents( '.wpforms-field-option-row-password-strength' ).data().fieldId, event.target.checked );
- }
- );
- $builder.on(
- 'change',
- '.wpforms-field-option-richtext .wpforms-field-option-row-media_enabled input',
- app.updateRichTextMediaFieldsLimitControls
- );
- $builder.on(
- 'change',
- '.wpforms-field-option-richtext .wpforms-field-option-row-style select',
- app.updateRichTextStylePreview
- );
- // File uploader - change style.
- $builder
- .on(
- 'change',
- '.wpforms-field-option-file-upload .wpforms-field-option-row-style select, .wpforms-field-option-file-upload .wpforms-field-option-row-max_file_number input',
- function( event ) {
- app.fieldFileUploadPreviewUpdate( event.target );
- }
- );
- // Real-time updates for Number Slider field.
- app.numberSliderEvents( $builder );
- // Hide image choices if dynamic choices is not off.
- app.fieldDynamicChoiceToggleImageChoices();
- // Real-time updates for Payment field's 'Show price after item label' option.
- $builder.on( 'change', '.wpforms-field-option-row-show_price_after_labels input', function( e ) {
- var $input = $( this ),
- $list = $input.closest( '.wpforms-field-option-group-basic' ).find( '.wpforms-field-option-row-choices .choices-list' );
- app.fieldChoiceUpdate( $list.data( 'field-type' ), $list.data( 'field-id' ) );
- } );
- $builder
- .on( 'input', '.wpforms-field-option-row-preview-notice textarea', app.updatePreviewNotice )
- .on( 'change', '.wpforms-field-option-row-preview-notice-enable input', app.toggleEntryPreviewNotice )
- .on( 'wpformsFieldAdd', app.maybeLockEntryPreviewGroupOnAdd )
- .on( 'wpformsFieldMove', app.maybeLockEntryPreviewGroupOnMove )
- .on( 'click', '.wpforms-entry-preview-block', app.entryPreviewBlockField );
- app.defaultStateEntryPreviewNotice();
- },
- /**
- * Determine if the field is disabled for selection/duplication/deletion.
- *
- * @since 1.7.1
- *
- * @param {mixed} el DOM element or jQuery object of some container on the field preview.
- *
- * @returns {bool} True if actions are disabled.
- */
- isFieldPreviewActionsDisabled: function( el ) {
- return $( el ).closest( '.wpforms-field-wrap' ).hasClass( 'ui-sortable-disabled' );
- },
- /**
- * Toggle field group visibility in the field sidebar.
- *
- * @since 1.0.0
- *
- * @param {mixed} el DOM element or jQuery object.
- * @param {string} action Action.
- */
- fieldGroupToggle: function( el, action ) {
- var $this = $( el ),
- $buttons = $this.next( '.wpforms-add-fields-buttons' ),
- $group = $buttons.parent(),
- $icon = $this.find( 'i' ),
- groupName = $this.data( 'group' ),
- cookieName = 'wpforms_field_group_' + groupName;
- if ( action === 'click' ) {
- if ( $group.hasClass( 'wpforms-closed' ) ) {
- wpCookies.remove( cookieName );
- } else {
- wpCookies.set( cookieName, 'true', 2592000 ); // 1 month
- }
- $icon.toggleClass( 'wpforms-angle-right' );
- $buttons.stop().slideToggle( '', function() {
- $group.toggleClass( 'wpforms-closed' );
- } );
- return;
- }
- if ( action === 'load' ) {
- $buttons = $this.find( '.wpforms-add-fields-buttons' );
- $icon = $this.find( '.wpforms-add-fields-heading i' );
- groupName = $this.find( '.wpforms-add-fields-heading' ).data( 'group' );
- cookieName = 'wpforms_field_group_' + groupName;
- if ( wpCookies.get( cookieName ) === 'true' ) {
- $icon.toggleClass( 'wpforms-angle-right' );
- $buttons.hide();
- $this.toggleClass( 'wpforms-closed' );
- }
- }
- },
- /**
- * Update description.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Element.
- * @param {string} value Value.
- */
- updateDescription: function( $el, value ) {
- if ( $el.hasClass( 'nl2br' ) ) {
- value = value.replace( /\n/g, '<br>' );
- }
- $el.html( value );
- },
- /**
- * Set default state for the entry preview notice field.
- *
- * @since 1.6.9
- */
- defaultStateEntryPreviewNotice: function() {
- $( '.wpforms-field-option-row-preview-notice-enable input' ).each( function() {
- $( this ).trigger( 'change' );
- } );
- },
- /**
- * Update a preview notice for the field preview.
- *
- * @since 1.6.9
- */
- updatePreviewNotice: function() {
- var $this = $( this ),
- value = wpf.sanitizeHTML( $this.val() ).trim(),
- id = $this.parent().data( 'field-id' ),
- $field = $( '#wpforms-field-' + id ).find( '.wpforms-entry-preview-notice' );
- value = value ? value : wpforms_builder.entry_preview_default_notice;
- app.updateDescription( $field, value );
- },
- /**
- * Show/hide entry preview notice for the field preview.
- *
- * @since 1.6.9
- */
- toggleEntryPreviewNotice: function() {
- var $this = $( this ),
- id = $this.closest( '.wpforms-field-option' ).data( 'field-id' ),
- $field = $( '#wpforms-field-' + id ),
- $noticeField = $( '#wpforms-field-option-' + id + ' .wpforms-field-option-row-preview-notice' ),
- $notice = $field.find( '.wpforms-entry-preview-notice' ),
- $defaultNotice = $field.find( '.wpforms-alert-info' );
- if ( $this.is( ':checked' ) ) {
- $defaultNotice.hide();
- $notice.show();
- $noticeField.show();
- return;
- }
- $noticeField.hide();
- $notice.hide();
- $defaultNotice.show();
- },
- /**
- * Delete a field.
- *
- * @param {int} id Field ID.
- *
- * @since 1.0.0
- * @since 1.6.9 Add the entry preview logic.
- */
- fieldDelete: function( id ) {
- var $field = $( '#wpforms-field-' + id ),
- type = $field.data( 'field-type' );
- if ( type === 'pagebreak' && $field.hasClass( 'wpforms-field-entry-preview-not-deleted' ) ) {
- app.youCantRemovePageBreakFieldPopup();
- return;
- }
- if ( $field.hasClass( 'no-delete' ) ) {
- app.youCantRemoveFieldPopup();
- return;
- }
- app.confirmFieldDeletion( id, type );
- },
- /**
- * Show the error message in the popup that you cannot remove the page break field.
- *
- * @since 1.6.9
- */
- youCantRemovePageBreakFieldPopup: function() {
- $.alert( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.entry_preview_require_page_break,
- icon: 'fa fa-exclamation-circle',
- type: 'red',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Show the error message in the popup that you cannot reorder the field.
- *
- * @since 1.7.1
- */
- youCantReorderFieldPopup: function() {
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.field_cannot_be_reordered,
- icon: 'fa fa-exclamation-circle',
- type: 'red',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Show the error message in the popup that you cannot remove the field.
- *
- * @since 1.6.9
- */
- youCantRemoveFieldPopup: function() {
- $.alert( {
- title: wpforms_builder.field_locked,
- content: wpforms_builder.field_locked_msg,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons: {
- confirm: {
- text: wpforms_builder.close,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Show the confirmation popup before the field deletion.
- *
- * @param {int} id Field ID.
- * @param {string} type Field type.
- *
- * @since 1.6.9
- */
- confirmFieldDeletion: function( id, type ) {
- var fieldData = {
- 'id' : id,
- 'message' : wpforms_builder.delete_confirm,
- };
- $builder.trigger( 'wpformsBeforeFieldDeleteAlert', [ fieldData ] );
- $.confirm( {
- title : false,
- content : fieldData.message,
- icon : 'fa fa-exclamation-circle',
- type : 'orange',
- buttons: {
- confirm: {
- text : wpforms_builder.ok,
- btnClass : 'btn-confirm',
- keys : [ 'enter' ],
- action: function() {
- app.fieldDeleteById( id, type );
- },
- },
- cancel: {
- text: wpforms_builder.cancel,
- },
- },
- } );
- },
- /**
- * Remove the field by ID.
- *
- * @since 1.6.9
- *
- * @param {int} id Field ID.
- * @param {string} type Field type.
- */
- fieldDeleteById: function( id, type ) {
- $( '#wpforms-field-' + id ).fadeOut( 400, function() {
- $builder.trigger( 'wpformsBeforeFieldDelete', [ id, type ] );
- $( this ).remove();
- $( '#wpforms-field-option-' + id ).remove();
- $( '.wpforms-field, .wpforms-title-desc' ).removeClass( 'active' );
- app.fieldTabToggle( 'add-fields' );
- if ( $( '.wpforms-field' ).length < 1 ) {
- elements.$fieldOptions.append( elements.$noFieldsOptions.clone() );
- elements.$sortableFieldsWrap.append( elements.$noFieldsPreview.clone() );
- $builder.find( '.wpforms-field-submit' ).hide();
- }
- $builder.trigger( 'wpformsFieldDelete', [ id, type ] );
- } );
- },
- /**
- * Load entry preview fields.
- *
- * @since 1.6.9
- */
- loadEntryPreviewFields: function() {
- var $fields = $( '.wpforms-field-wrap .wpforms-field-entry-preview' );
- if ( ! $fields.length ) {
- return;
- }
- $fields.each( function() {
- app.lockEntryPreviewFieldsPosition( $( this ).data( 'field-id' ) );
- } );
- },
- /**
- * Delete the entry preview field from the form preview.
- *
- * @since 1.6.9
- *
- * @param {Event} event Event.
- * @param {int} id Field ID.
- * @param {string} type Field type.
- */
- fieldEntryPreviewDelete: function( event, id, type ) {
- if ( 'entry-preview' !== type ) {
- return;
- }
- var $field = $( '#wpforms-field-' + id ),
- $previousPageBreakField = $field.prevAll( '.wpforms-field-pagebreak' ),
- $nextPageBreakField = $field.nextAll( '.wpforms-field-pagebreak' ),
- nextPageBreakId = $nextPageBreakField.data( 'field-id' ),
- $nextPageBreakOptions = $( '#wpforms-field-option-' + nextPageBreakId );
- $previousPageBreakField.removeClass( 'wpforms-field-not-draggable wpforms-field-entry-preview-not-deleted' );
- $nextPageBreakOptions.find( '.wpforms-entry-preview-block' ).removeClass( 'wpforms-entry-preview-block' );
- },
- /**
- * Maybe lock the entry preview and fields nearby after move event.
- *
- * @since 1.6.9
- *
- * @param {Event} e Event.
- * @param {object} ui UI sortable object.
- */
- maybeLockEntryPreviewGroupOnMove: function( e, ui ) {
- if ( ! ui.item.hasClass( 'wpforms-field-pagebreak' ) ) {
- return;
- }
- app.maybeLockEntryPreviewGroupOnAdd( e, ui.item.data( 'field-id' ), 'pagebreak' );
- },
- /**
- * Maybe lock the entry preview and fields nearby after add event.
- *
- * @since 1.6.9
- *
- * @param {Event} e Event.
- * @param {int} fieldId Field id.
- * @param {string} type Field type.
- */
- maybeLockEntryPreviewGroupOnAdd: function( e, fieldId, type ) {
- if ( type !== 'pagebreak' ) {
- return;
- }
- var $currentField = $( '#wpforms-field-' + fieldId ),
- $currentFieldPrevToggle = $( '#wpforms-field-option-' + fieldId + ' .wpforms-field-option-row-prev_toggle' ),
- $currentFieldPrevToggleField = $currentFieldPrevToggle.find( 'input' ),
- $prevField = $currentField.prevAll( '.wpforms-field-entry-preview,.wpforms-field-pagebreak' ).first(),
- $prevFieldPrevToggle = $( '#wpforms-field-option-' + $prevField.data( 'field-id' ) + ' .wpforms-field-option-row-prev_toggle' ),
- $prevFieldPrevToggleField = $prevFieldPrevToggle.find( 'input' ),
- $nextField = $currentField.nextAll( '.wpforms-field-entry-preview,.wpforms-field-pagebreak' ).first(),
- $nextFieldPrevToggle = $( '#wpforms-field-option-' + $nextField.data( 'field-id' ) + ' .wpforms-field-option-row-prev_toggle' );
- if ( ! $prevField.hasClass( 'wpforms-field-entry-preview' ) && ! $nextField.hasClass( 'wpforms-field-entry-preview' ) ) {
- return;
- }
- if ( $prevField.hasClass( 'wpforms-field-entry-preview' ) ) {
- $currentFieldPrevToggleField.attr( 'checked', 'checked' ).trigger( 'change' );
- $currentFieldPrevToggle.addClass( 'wpforms-entry-preview-block' );
- $nextFieldPrevToggle.removeClass( 'wpforms-entry-preview-block' );
- return;
- }
- $currentField.addClass( 'wpforms-field-not-draggable wpforms-field-entry-preview-not-deleted' );
- $prevField.removeClass( 'wpforms-field-not-draggable wpforms-field-entry-preview-not-deleted' );
- if ( $prevField.prevAll( '.wpforms-field-entry-preview,.wpforms-field-pagebreak' ).first().hasClass( 'wpforms-field-entry-preview' ) ) {
- $prevFieldPrevToggleField.attr( 'checked', 'checked' ).trigger( 'change' );
- $prevFieldPrevToggle.addClass( 'wpforms-entry-preview-block' );
- }
- },
- /**
- * Show the error popup that the entry preview field blocks the field.
- *
- * @since 1.6.9
- *
- * @param {Event} e Event.
- */
- entryPreviewBlockField: function( e ) {
- e.preventDefault();
- $.alert( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.entry_preview_require_previous_button,
- icon: 'fa fa-exclamation-circle',
- type: 'red',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Is it an entry preview field that should be checked before adding?
- *
- * @since 1.6.9
- *
- * @param {string} type Field type.
- * @param {object} options Field options.
- *
- * @returns {boolean} True when we should check it.
- */
- isUncheckedEntryPreviewField: function( type, options ) {
- return type === 'entry-preview' && ( ! options || options && ! options.passed );
- },
- /**
- * Add an entry preview field to the form preview.
- *
- * @since 1.6.9
- *
- * @param {string} type Field type.
- * @param {object} options Field options.
- */
- addEntryPreviewField: function( type, options ) { // eslint-disable-line complexity
- var addButton = $( '#wpforms-add-fields-entry-preview' );
- if ( addButton.hasClass( 'wpforms-entry-preview-adding' ) ) {
- return;
- }
- var $fields = $( '.wpforms-field-wrap .wpforms-field' ),
- position = options && options.position ? options.position : $fields.length,
- needPageBreakBefore = app.isEntryPreviewFieldRequiresPageBreakBefore( $fields, position ),
- needPageBreakAfter = app.isEntryPreviewFieldRequiresPageBreakAfter( $fields, position );
- addButton.addClass( 'wpforms-entry-preview-adding' );
- if ( ! options ) {
- options = {};
- }
- options.passed = true;
- if ( ! needPageBreakBefore && ! needPageBreakAfter ) {
- app.fieldAdd( 'entry-preview', options ).done( function( res ) {
- app.lockEntryPreviewFieldsPosition( res.data.field.id );
- } );
- return;
- }
- if ( needPageBreakBefore ) {
- app.addPageBreakAndEntryPreviewFields( options, position );
- return;
- }
- app.addEntryPreviewAndPageBreakFields( options, position );
- },
- /**
- * Add the entry preview field after the page break field.
- * We should wait for the page break adding to avoid id duplication.
- *
- * @since 1.6.9
- *
- * @param {object} options Field options.
- */
- addEntryPreviewFieldAfterPageBreak: function( options ) {
- var checkExist = setInterval( function() {
- if ( $( '.wpforms-field-wrap .wpforms-pagebreak-bottom, .wpforms-field-wrap .wpforms-pagebreak-top' ).length === 2 ) {
- app.fieldAdd( 'entry-preview', options ).done( function( res ) {
- app.lockEntryPreviewFieldsPosition( res.data.field.id );
- } );
- clearInterval( checkExist );
- }
- }, 100 );
- },
- /**
- * Add the entry preview field after the page break field.
- *
- * @since 1.6.9
- *
- * @param {object} options Field options.
- * @param {int} position The field position.
- */
- addPageBreakAndEntryPreviewFields: function( options, position ) {
- var hasPageBreak = $( '.wpforms-field-wrap .wpforms-field-pagebreak' ).length >= 3;
- app.fieldAdd( 'pagebreak', { 'position': position } ).done( function( res ) {
- options.position = hasPageBreak ? position + 1 : position + 2;
- app.addEntryPreviewFieldAfterPageBreak( options );
- var $pageBreakOptions = $( '#wpforms-field-option-' + res.data.field.id ),
- $pageBreakPrevToggle = $pageBreakOptions.find( '.wpforms-field-option-row-prev_toggle' ),
- $pageBreakPrevToggleField = $pageBreakPrevToggle.find( 'input' );
- $pageBreakPrevToggleField.attr( 'checked', 'checked' ).trigger( 'change' );
- $pageBreakPrevToggle.addClass( 'wpforms-entry-preview-block' );
- } );
- },
- /**
- * Duplicate field
- *
- * @since 1.2.9
- */
- fieldDuplicate: function(id) {
- var $field = $('#wpforms-field-'+id),
- type = $field.data('field-type');
- if ($field.hasClass('no-duplicate')) {
- $.alert({
- title: wpforms_builder.field_locked,
- content: wpforms_builder.field_locked_msg,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons : {
- confirm : {
- text: wpforms_builder.close,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- }
- }
- });
- } else {
- $.confirm({
- title: false,
- content: wpforms_builder.duplicate_confirm,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- var $fieldOptions = $( '#wpforms-field-option-' + id ),
- isModernDropdown = app.dropdownField.helpers.isModernSelect( $field.find( '.primary-input' ) );
- // Restore tooltips before cloning.
- wpf.restoreTooltips( $fieldOptions );
- // Force Modern Dropdown conversion to classic before cloning.
- if ( isModernDropdown ) {
- app.dropdownField.helpers.convertModernToClassic( id );
- }
- var $newField = $field.clone(),
- newFieldOptions = $fieldOptions.html(),
- newFieldID = $('#wpforms-field-id').val(),
- $labelField = $( '#wpforms-field-option-' + id + '-label' ).length ? $( '#wpforms-field-option-' + id + '-label' ) : $( '#wpforms-field-option-' + id + '-name' ),
- newFieldLabel = $labelField.length ? $labelField.val() + ' ' + wpforms_builder.duplicate_copy : wpforms_builder.field + ' #' + id + ' ' + wpforms_builder.duplicate_copy,
- nextID = Number(newFieldID)+1,
- regex_fieldOptionsID = new RegExp( 'ID #'+id, "g"),
- regex_fieldID = new RegExp( 'fields\\['+id+'\\]', "g"),
- regex_dataFieldID = new RegExp( 'data-field-id="'+id+'"', "g"),
- regex_referenceID = new RegExp( 'data-reference="'+id+'"', "g"),
- regex_elementID = new RegExp( '\\b(id|for)="wpforms-(.*?)'+id+'(.*?)"', "ig");
- // Toggle visibility states
- $field.after($newField);
- $field.removeClass('active');
- $newField.addClass('active').attr({
- 'id' : 'wpforms-field-'+newFieldID,
- 'data-field-id': newFieldID
- });
- // Various regex to adjust the field options to work with
- // the new field ID
- function regex_elementID_replace(match, p1, p2, p3, offset, string) {
- return p1+'="wpforms-'+p2+newFieldID+p3+'"';
- }
- newFieldOptions = newFieldOptions.replace(regex_fieldOptionsID, 'ID #'+newFieldID);
- newFieldOptions = newFieldOptions.replace(regex_fieldID, 'fields['+newFieldID+']');
- newFieldOptions = newFieldOptions.replace(regex_dataFieldID, 'data-field-id="'+newFieldID+'"');
- newFieldOptions = newFieldOptions.replace(regex_referenceID, 'data-reference="'+newFieldID+'"');
- newFieldOptions = newFieldOptions.replace(regex_elementID, regex_elementID_replace);
- // Add new field options panel
- $fieldOptions.hide().after( '<div class="' + $fieldOptions.attr( 'class' ) + '" id="wpforms-field-option-' + newFieldID + '" data-field-id="' + newFieldID + '">' + newFieldOptions + '</div>' );
- var $newFieldOptions = $('#wpforms-field-option-'+newFieldID);
- // Copy over values
- $fieldOptions.find(':input').each(function(index, el) {
- var $this = $(this),
- name = $this.attr('name');
- if ( ! name ) {
- return 'continue';
- }
- var newName = name.replace(regex_fieldID, 'fields['+newFieldID+']'),
- type = $this.attr('type');
- if ( type === 'checkbox' || type === 'radio' ) {
- if ($this.is(':checked')){
- $newFieldOptions.find('[name="'+newName+'"]').prop('checked', true).attr('checked','checked');
- } else {
- $newFieldOptions.find('[name="'+newName+'"]').prop('checked', false).attr('checked',false);
- }
- } else if ($this.is('select')) {
- if ($this.find('option:selected').length) {
- var optionVal = $this.find('option:selected').val();
- $newFieldOptions.find('[name="'+newName+'"]').find('[value="'+optionVal+'"]').prop('selected',true);
- }
- } else {
- if ($this.val() !== '') {
- $newFieldOptions.find('[name="'+newName+'"]').val( $this.val() );
- } else if ( $this.hasClass( 'wpforms-money-input' ) ) {
- $newFieldOptions.find( '[name="' + newName + '"]' ).val(
- wpf.numberFormat( '0', wpforms_builder.currency_decimals, wpforms_builder.currency_decimal, wpforms_builder.currency_thousands )
- );
- }
- }
- });
- // ID adjustments.
- $( '#wpforms-field-option-' + newFieldID ).find( '.wpforms-field-option-hidden-id' ).val( newFieldID );
- $( '#wpforms-field-id' ).val( nextID );
- // Adjust label to indicate this is a copy.
- $( '#wpforms-field-option-' + newFieldID + '-label' ).val( newFieldLabel );
- // For the HTML field we should change the internal label called `name`.
- if ( type === 'html' ) {
- $( '#wpforms-field-option-' + newFieldID + '-name' ).val( newFieldLabel );
- }
- $newField.find( '.label-title .text' ).text( newFieldLabel );
- // Fire field add custom event.
- $builder.trigger( 'wpformsFieldAdd', [ newFieldID, type ] );
- // Re-init tooltips for new field options panel.
- wpf.initTooltips();
- // Re-init Modern Dropdown.
- if ( isModernDropdown ) {
- app.dropdownField.helpers.convertClassicToModern( id );
- app.dropdownField.helpers.convertClassicToModern( newFieldID );
- }
- // Re-init instance in choices related fields.
- app.fieldChoiceUpdate( $newField.data( 'field-type' ), newFieldID );
- // Lastly, update the next ID stored in database.
- $.post(
- wpforms_builder.ajax_url,
- {
- form_id : s.formID,
- nonce : wpforms_builder.nonce,
- action : 'wpforms_builder_increase_next_field_id',
- }
- );
- },
- },
- cancel: {
- text: wpforms_builder.cancel,
- },
- },
- } );
- }
- },
- /**
- * Add the entry preview field before the page break field.
- *
- * @since 1.6.9
- *
- * @param {object} options Field options.
- * @param {int} position The field position.
- */
- addEntryPreviewAndPageBreakFields: function( options, position ) {
- app.fieldAdd( 'entry-preview', options ).done( function( res ) {
- var entryPreviewId = res.data.field.id;
- app.fieldAdd( 'pagebreak', { 'position': position + 1 } ).done( function() {
- app.lockEntryPreviewFieldsPosition( entryPreviewId );
- } );
- } );
- },
- /**
- * Stick an entry preview field after adding.
- *
- * @since 1.6.9
- *
- * @param {int} id ID.
- */
- lockEntryPreviewFieldsPosition: function( id ) {
- var $entryPreviewField = $( '#wpforms-field-' + id ),
- $pageBreakField = $entryPreviewField.prevAll( '.wpforms-field-pagebreak:not(.wpforms-pagebreak-bottom)' ).first(),
- $nextPageBreakField = $entryPreviewField.nextAll( '.wpforms-field-pagebreak' ).first(),
- pageBreakFieldId = $nextPageBreakField.data( 'field-id' ),
- $pageBreakOptions = $( '#wpforms-field-option-' + pageBreakFieldId ),
- $pageBreakPrevToggle = $pageBreakOptions.find( '.wpforms-field-option-row-prev_toggle' ),
- $pageBreakPrevToggleField = $pageBreakPrevToggle.find( 'input' );
- $entryPreviewField.addClass( 'wpforms-field-not-draggable' );
- $pageBreakField.addClass( 'wpforms-field-not-draggable wpforms-field-entry-preview-not-deleted' );
- $pageBreakPrevToggleField.attr( 'checked', 'checked' ).trigger( 'change' );
- $pageBreakPrevToggle.addClass( 'wpforms-entry-preview-block' );
- $( '#wpforms-add-fields-entry-preview' ).removeClass( 'wpforms-entry-preview-adding' );
- },
- /**
- * An entry preview field requires a page break that locates before.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $fields List of fields in the form preview.
- * @param {int} position The field position.
- *
- * @returns {boolean} True if need add an page break field before.
- */
- isEntryPreviewFieldRequiresPageBreakBefore: function( $fields, position ) {
- var $beforeFields = $fields.slice( 0, position ).filter( '.wpforms-field-pagebreak,.wpforms-field-entry-preview' ),
- needPageBreakBefore = true;
- if ( ! $beforeFields.length ) {
- return needPageBreakBefore;
- }
- $( $beforeFields.get().reverse() ).each( function() {
- var $this = $( this );
- if ( $this.hasClass( 'wpforms-field-entry-preview' ) ) {
- return false;
- }
- if ( $this.hasClass( 'wpforms-field-pagebreak' ) && ! $this.hasClass( 'wpforms-field-stick' ) ) {
- needPageBreakBefore = false;
- return false;
- }
- } );
- return needPageBreakBefore;
- },
- /**
- * An entry preview field requires a page break that locates after.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $fields List of fields in the form preview.
- * @param {int} position The field position.
- *
- * @returns {boolean} True if need add an page break field after.
- */
- isEntryPreviewFieldRequiresPageBreakAfter: function( $fields, position ) {
- var $afterFields = $fields.slice( position ).filter( '.wpforms-field-pagebreak,.wpforms-field-entry-preview' ),
- needPageBreakAfter = Boolean( $afterFields.length );
- if ( ! $afterFields.length ) {
- return needPageBreakAfter;
- }
- $afterFields.each( function() {
- var $this = $( this );
- if ( $this.hasClass( 'wpforms-field-entry-preview' ) ) {
- return false;
- }
- if ( $this.hasClass( 'wpforms-field-pagebreak' ) ) {
- needPageBreakAfter = false;
- return false;
- }
- } );
- return needPageBreakAfter;
- },
- /**
- * Add new field.
- *
- * @since 1.0.0
- * @since 1.6.4 Added hCaptcha support.
- */
- fieldAdd: function(type, options) {
- var $btn = $( '#wpforms-add-fields-' + type );
- if ( $btn.hasClass( 'upgrade-modal' ) || $btn.hasClass( 'education-modal' ) || $btn.hasClass( 'warning-modal' ) ) {
- return;
- }
- if ( -1 !== $.inArray( type, [ 'captcha_hcaptcha', 'captcha_recaptcha', 'captcha_none' ] ) ) {
- app.captchaUpdate();
- return;
- }
- adding = true;
- app.disableDragAndDrop();
- if ( app.isUncheckedEntryPreviewField( type, options ) ) {
- app.addEntryPreviewField( type, options );
- return;
- }
- var defaults = {
- position : 'bottom',
- placeholder: false,
- scroll : true,
- defaults : false
- };
- options = $.extend( {}, defaults, options);
- var data = {
- action : 'wpforms_new_field_'+type,
- id : s.formID,
- type : type,
- defaults: options.defaults,
- nonce : wpforms_builder.nonce
- };
- return $.post(wpforms_builder.ajax_url, data, function(res) {
- if (res.success) {
- var totalFields = $('.wpforms-field').length,
- $preview = $('#wpforms-panel-fields .wpforms-panel-content-wrap'),
- $lastField = $('.wpforms-field').last(),
- $newField = $(res.data.preview),
- $newOptions = $(res.data.options);
- adding = false;
- $newField.css( 'display', 'none' );
- if (options.placeholder) {
- options.placeholder.remove();
- }
- // Determine where field gets placed
- if ( options.position === 'bottom' ) {
- if ( $lastField.length && $lastField.hasClass( 'wpforms-field-stick' ) ) {
- // Check to see if the last field we have is configured to
- // be stuck to the bottom, if so add the field above it.
- $( '.wpforms-field-wrap' ).children( ':eq(' + ( totalFields - 1 ) + ')' ).before( $newField );
- $( '.wpforms-field-options' ).children( ':eq(' + ( totalFields - 1 ) + ')' ).before( $newOptions );
- } else {
- // Add field to bottom
- $( '.wpforms-field-wrap' ).append( $newField );
- $( '.wpforms-field-options' ).append( $newOptions );
- }
- } else if ( options.position === 'top' ) {
- // Add field to top, scroll to
- $( '.wpforms-field-wrap' ).prepend( $newField );
- $( '.wpforms-field-options' ).prepend( $newOptions );
- } else {
- if ( options.position === totalFields && $lastField.length && $lastField.hasClass( 'wpforms-field-stick' ) ) {
- // Check to see if the user tried to add the field at
- // the end BUT the last field we have is configured to
- // be stuck to the bottom, if so add the field above it.
- $( '.wpforms-field-wrap' ).children( ':eq(' + ( totalFields - 1 ) + ')' ).before( $newField );
- $( '.wpforms-field-options' ).children( ':eq(' + ( totalFields - 1 ) + ')' ).before( $newOptions );
- } else if ( $( '.wpforms-field-wrap' ).find( '.wpforms-field' ).eq( options.position ).length ) {
- // Add field to a specific location.
- $( '.wpforms-field-wrap' ).find( '.wpforms-field' ).eq( options.position ).before( $newField );
- $( '.wpforms-field-options' ).find( '.wpforms-field-option' ).eq( options.position ).before( $newOptions );
- } else {
- // Something's wrong, just add the field. This should never occur.
- $( '.wpforms-field-wrap' ).append( $newField );
- $( '.wpforms-field-options' ).append( $newOptions );
- }
- }
- $newField.fadeIn();
- $builder.find( '.no-fields, .no-fields-preview' ).remove();
- $builder.find( '.wpforms-field-submit' ).show();
- // Scroll to the desired position.
- if ( options.scroll && options.position.length ) {
- var scrollTop = $preview.scrollTop(),
- newFieldPosition = $newField.position().top,
- scrollAmount = newFieldPosition > scrollTop ? newFieldPosition - scrollTop : newFieldPosition + scrollTop;
- $preview.animate(
- {
- // Position `bottom` actually means that we need to scroll to the newly added field.
- scrollTop: options.position === 'bottom' ? scrollAmount : 0,
- },
- 1000
- );
- }
- $( '#wpforms-field-id' ).val( res.data.field.id + 1 );
- wpf.initTooltips();
- app.loadColorPickers();
- app.toggleAllOptionGroups();
- $builder.trigger( 'wpformsFieldAdd', [ res.data.field.id, type ] );
- } else {
- console.log( res );
- }
- } ).fail( function( xhr, textStatus, e ) {
- adding = false;
- console.log( xhr.responseText );
- } ).always( function() {
- $builder.find( '.wpforms-add-fields .wpforms-add-fields-button' ).prop( 'disabled', false );
- if ( ! adding ) {
- app.enableDragAndDrop();
- }
- } );
- },
- /**
- * Update CAPTCHA form setting.
- *
- * @since 1.6.4
- *
- * @returns {object} jqXHR
- */
- captchaUpdate: function() {
- var data = {
- action : 'wpforms_update_field_captcha',
- id : s.formID,
- nonce : wpforms_builder.nonce,
- };
- return $.post( wpforms_builder.ajax_url, data, function( res ) {
- if ( res.success ) {
- var args = {
- title: false,
- content: false,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- boxWidth: '450px',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- },
- $enableCheckbox = $( '#wpforms-panel-field-settings-recaptcha' ),
- caseName = res.data.current;
- $enableCheckbox.data( 'provider', res.data.provider );
- // Possible cases:
- //
- // not_configured - IF CAPTCHA is not configured in the WPForms plugin settings
- // configured_not_enabled - IF CAPTCHA is configured in WPForms plugin settings, but wasn't set in form settings
- // configured_enabled - IF CAPTCHA is configured in WPForms plugin and form settings
- if ( 'configured_not_enabled' === caseName || 'configured_enabled' === caseName ) {
- // Get a correct case name.
- caseName = $enableCheckbox.prop( 'checked' ) ? 'configured_enabled' : 'configured_not_enabled';
- // Check/uncheck a `CAPTCHA` checkbox in form setting.
- args.buttons.confirm.action = function() {
- $enableCheckbox.prop( 'checked', ( 'configured_not_enabled' === caseName ) ).trigger( 'change' );
- };
- }
- args.title = res.data.cases[ caseName ].title;
- args.content = res.data.cases[ caseName ].content;
- // Do you need a Cancel button?
- if ( res.data.cases[ caseName ].cancel ) {
- args.buttons.cancel = {
- text: wpforms_builder.cancel,
- keys: [ 'esc' ],
- };
- }
- // Call a Confirm modal.
- $.confirm( args );
- } else {
- console.log( res );
- }
- } ).fail( function( xhr, textStatus, e ) {
- console.log( xhr.responseText );
- } );
- },
- /**
- * Disable drag & drop.
- *
- * @since 1.7.1
- */
- disableDragAndDrop: function() {
- elements.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'disable' );
- elements.$sortableFieldsWrap.filter( '.ui-sortable' ).sortable( 'disable' );
- },
- /**
- * Enable drag & drop.
- *
- * @since 1.7.1
- */
- enableDragAndDrop: function() {
- elements.$addFieldsButtons.filter( '.ui-draggable' ).draggable( 'enable' );
- elements.$sortableFieldsWrap.filter( '.ui-sortable' ).sortable( 'enable' );
- },
- /**
- * Sortable fields in the builder form preview area.
- *
- * @since 1.0.0
- */
- fieldSortable: function() {
- var fieldOptions = $( '.wpforms-field-options' ),
- fieldReceived = false,
- fieldIndex,
- fieldIndexNew,
- field,
- fieldNew,
- $scrollContainer = $( '#wpforms-panel-fields .wpforms-panel-content-wrap' ),
- currentlyScrolling = false;
- elements.$sortableFieldsWrap.sortable( {
- items : '> .wpforms-field:not(.wpforms-field-stick):not(.no-fields-preview)',
- axis : 'y',
- delay : 100,
- opacity: 0.75,
- cursor : 'move',
- start: function( e, ui ) {
- fieldIndex = ui.item.index();
- field = fieldOptions[0].children[fieldIndex];
- },
- stop: function( e, ui ) {
- fieldIndexNew = ui.item.index();
- fieldNew = fieldOptions[ 0 ].children[ fieldIndexNew ];
- if ( fieldIndex < fieldIndexNew ) {
- $( fieldNew ).after( field );
- } else {
- $( fieldNew ).before( field );
- }
- $builder.trigger( 'wpformsFieldMove', ui );
- fieldReceived = false;
- },
- over: function( e, ui ) {
- var $el = ui.item.first();
- $el.addClass( 'wpforms-field-dragging' );
- if ( $el.hasClass( 'wpforms-field-drag' ) ) {
- var width = $( '.wpforms-field' ).outerWidth() || elements.$sortableFieldsWrap.find( '.no-fields-preview' ).outerWidth();
- $el.addClass( 'wpforms-field-drag-over' ).removeClass( 'wpforms-field-drag-out' ).css( 'width', width ).css( 'height', 'auto' );
- }
- },
- out: function( e, ui ) {
- var $el = ui.item.first();
- $el.removeClass( 'wpforms-field-dragging' );
- if ( ! fieldReceived ) {
- var width = $el.attr( 'data-original-width' );
- if ( $el.hasClass( 'wpforms-field-drag' ) ) {
- $el.addClass( 'wpforms-field-drag-out' ).removeClass( 'wpforms-field-drag-over' ).css( { 'width': width, 'left': '', 'top': '' } );
- }
- }
- $el.css( {
- 'top': '',
- 'left': '',
- 'z-index': '',
- } );
- },
- receive: function( e, ui ) {
- fieldReceived = true;
- var pos = $( this ).data( 'ui-sortable' ).currentItem.index(),
- $el = ui.helper,
- type = $el.attr( 'data-field-type' );
- $el.addClass( 'wpforms-field-drag-over wpforms-field-drag-pending' ).removeClass( 'wpforms-field-drag-out' ).css( 'width', '100%' );
- $el.append( s.spinnerInline );
- $builder.find( '.wpforms-add-fields .wpforms-add-fields-button' ).prop( 'disabled', true );
- $builder.find( '.no-fields-preview' ).remove();
- app.fieldAdd( type, { position: pos, placeholder: $el } );
- },
- sort: function( e, ui ) {
- if ( currentlyScrolling ) {
- return;
- }
- var scrollAreaHeight = 50,
- operator,
- mouseYPosition = e.clientY,
- containerOffset = $scrollContainer.offset(),
- containerHeight = $scrollContainer.height(),
- containerBottom = containerOffset.top + containerHeight;
- if (
- mouseYPosition > containerOffset.top &&
- mouseYPosition < ( containerOffset.top + scrollAreaHeight )
- ) {
- operator = '-=';
- } else if (
- mouseYPosition > ( containerBottom - scrollAreaHeight ) &&
- mouseYPosition < containerBottom
- ) {
- operator = '+=';
- } else {
- return;
- }
- currentlyScrolling = true;
- $scrollContainer.animate(
- {
- scrollTop: operator + containerHeight / 3 + 'px',
- },
- 800,
- function() {
- currentlyScrolling = false;
- }
- );
- },
- cancel: '.wpforms-field-not-draggable',
- } );
- // Show popup in case if field is not draggable, cancel moving.
- var startTopPosition;
- $( '.wpforms-field-not-draggable, .wpforms-field-stick' ).draggable( {
- revert: true,
- axis: 'y',
- delay : 100,
- opacity: 0.75,
- cursor : 'move',
- start: function( event, ui ) {
- startTopPosition = ui.position.top;
- },
- drag: function( event, ui ) {
- if ( Math.abs( ui.position.top ) - Math.abs( startTopPosition ) > 15 ) {
- app.youCantReorderFieldPopup();
- return false;
- }
- },
- } );
- $( '.wpforms-add-fields-button' )
- .not( '.not-draggable' )
- .not( '.warning-modal' )
- .not( '.education-modal' )
- .draggable( {
- connectToSortable: '.wpforms-field-wrap',
- delay: 200,
- helper: function() {
- var $this = $( this ),
- width = $this.outerWidth(),
- text = $this.html(),
- type = $this.data( 'field-type' ),
- $el = $( '<div class="wpforms-field-drag-out wpforms-field-drag">' );
- return $el.html( text ).css( 'width', width ).attr( {'data-original-width': width, 'data-field-type': type } );
- },
- revert: 'invalid',
- cancel: false,
- scroll: false,
- opacity: 0.75,
- containment: 'document',
- } );
- elements.$addFieldsButtons.draggable( {
- connectToSortable: '.wpforms-field-wrap',
- delay: 200,
- helper: function() {
- var $this = $( this ),
- width = $this.outerWidth(),
- text = $this.html(),
- type = $this.data( 'field-type' ),
- $el = $( '<div class="wpforms-field-drag-out wpforms-field-drag">' );
- return $el.html( text ).css( 'width', width ).attr( { 'data-original-width': width, 'data-field-type': type } );
- },
- revert: 'invalid',
- cancel: false,
- scroll: false,
- opacity: 0.75,
- containment: 'document',
- } );
- },
- /**
- * Add new field choice
- *
- * @since 1.0.0
- */
- fieldChoiceAdd: function( event, el ) {
- event.preventDefault();
- var $this = $( el ),
- $parent = $this.parent(),
- checked = $parent.find( 'input.default' ).is( ':checked' ),
- fieldID = $this.closest( '.wpforms-field-option-row-choices' ).data( 'field-id' ),
- id = $parent.parent().attr( 'data-next-id' ),
- type = $parent.parent().data( 'field-type' ),
- $choice = $parent.clone().insertAfter( $parent );
- $choice.attr( 'data-key', id );
- $choice.find( 'input.label' ).val( '' ).attr( 'name', 'fields['+fieldID+'][choices]['+id+'][label]' );
- $choice.find( 'input.value' ).val( '' ).attr( 'name', 'fields['+fieldID+'][choices]['+id+'][value]' );
- $choice.find( 'input.source' ).val( '' ).attr( 'name', 'fields['+fieldID+'][choices]['+id+'][image]' );
- $choice.find( 'input.default').attr( 'name', 'fields['+fieldID+'][choices]['+id+'][default]' ).prop( 'checked', false );
- $choice.find( '.preview' ).empty();
- $choice.find( '.wpforms-image-upload-add' ).show();
- $choice.find( '.wpforms-money-input' ).trigger( 'focusout' );
- if ( checked === true ) {
- $parent.find( 'input.default' ).prop( 'checked', true );
- }
- id++;
- $parent.parent().attr( 'data-next-id', id );
- $builder.trigger( 'wpformsFieldChoiceAdd' );
- app.fieldChoiceUpdate( type, fieldID );
- },
- /**
- * Delete field choice
- *
- * @since 1.0.0
- */
- fieldChoiceDelete: function( e, el ) {
- e.preventDefault();
- var $this = $( el ),
- $list = $this.parent().parent(),
- total = $list.find( 'li' ).length,
- fieldData = {
- 'id' : $list.data( 'field-id' ),
- 'choiceId' : $this.closest( 'li' ).data( 'key' ),
- 'message' : '<strong>' + wpforms_builder.delete_choice_confirm + '</strong>',
- 'trigger' : false,
- };
- $builder.trigger( 'wpformsBeforeFieldDeleteAlert', [ fieldData ] );
- if ( total === 1 ) {
- app.fieldChoiceDeleteAlert();
- } else {
- var deleteChoice = function() {
- $this.parent().remove();
- app.fieldChoiceUpdate( $list.data( 'field-type' ), $list.data( 'field-id' ) );
- $builder.trigger( 'wpformsFieldChoiceDelete' );
- };
- if ( ! fieldData.trigger ) {
- deleteChoice();
- return;
- }
- $.confirm( {
- title: false,
- content: fieldData.message,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- deleteChoice();
- },
- },
- cancel: {
- text: wpforms_builder.cancel,
- },
- },
- } );
- }
- },
- /**
- * Field choice delete error alert.
- *
- * @since 1.6.7
- */
- fieldChoiceDeleteAlert: function() {
- $.alert( {
- title: false,
- content: wpforms_builder.error_choice,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Make field choices sortable.
- *
- * Currently used for select, radio, and checkboxes field types
- *
- * @since 1.0.0
- */
- fieldChoiceSortable: function(type, selector) {
- selector = typeof selector !== 'undefined' ? selector : '.wpforms-field-option-'+type+' .wpforms-field-option-row-choices ul';
- $(selector).sortable({
- items : 'li',
- axis : 'y',
- delay : 100,
- opacity: 0.6,
- handle : '.move',
- stop:function(e,ui){
- var id = ui.item.parent().data('field-id');
- app.fieldChoiceUpdate(type, id);
- $builder.trigger('wpformsFieldChoiceMove', ui);
- },
- update:function(e,ui){
- }
- });
- },
- /**
- * Generate Choice label. Used in field preview template.
- *
- * @since 1.6.2
- *
- * @param {object} data Template data.
- * @param {numeric} choiceID Choice ID.
- *
- * @returns {string} Label.
- */
- fieldChoiceLabel: function( data, choiceID ) {
- var label = typeof data.settings.choices[choiceID].label !== 'undefined' && data.settings.choices[choiceID].label.length !== 0 ?
- wpf.sanitizeHTML( data.settings.choices[choiceID].label ) :
- wpforms_builder.choice_empty_label_tpl.replace( '{number}', choiceID );
- if ( data.settings.show_price_after_labels ) {
- label += ' - ' + wpf.amountFormatCurrency( data.settings.choices[choiceID].value );
- }
- return label;
- },
- /**
- * Update field choices in preview area, for the Fields panel.
- *
- * Currently used for select, radio, and checkboxes field types.
- *
- * @since 1.0.0
- */
- fieldChoiceUpdate: function( type, id ) {
- var $primary = $( '#wpforms-field-' + id + ' .primary-input' );
- // Radio, Checkbox, and Payment Multiple/Checkbox use _ template.
- if ( 'radio' === type || 'checkbox' === type || 'payment-multiple' === type || 'payment-checkbox' === type ) {
- var fieldSettings = wpf.getField( id ),
- order = wpf.getChoicesOrder( id ),
- slicedChoices = {},
- slicedOrder = order.slice( 0, 20 ),
- tmpl = wp.template( 'wpforms-field-preview-checkbox-radio-payment-multiple' ),
- data = {
- settings: fieldSettings,
- order: slicedOrder,
- type: 'radio',
- };
- // Slice choices for preview.
- slicedOrder.forEach( function( entry ) {
- slicedChoices[ entry ] = fieldSettings.choices[ entry ];
- } );
- fieldSettings.choices = slicedChoices;
- if ( 'checkbox' === type || 'payment-checkbox' === type ) {
- data.type = 'checkbox';
- }
- $( '#wpforms-field-' + id ).find( 'ul.primary-input' ).replaceWith( tmpl( data ) );
- // Toggle limit choices alert message.
- app.firstNChoicesAlert( id, order.length );
- return;
- }
- var isModernSelect = app.dropdownField.helpers.isModernSelect( $primary ),
- newChoice = '';
- // Multiple payment choices are radio buttons.
- if ( 'payment-multiple' === type ) {
- type = 'radio';
- }
- // Checkbox payment choices are checkboxes.
- if ( 'payment-checkbox' === type ) {
- type = 'checkbox';
- }
- // Dropdown payment choices are selects.
- if ( 'payment-select' === type ) {
- type = 'select';
- }
- if ( 'select' === type ) {
- newChoice = '<option value="{label}">{label}</option>';
- $primary.find( 'option' ).not( '.placeholder' ).remove();
- } else if ( 'radio' === type || 'checkbox' === type || 'gdpr-checkbox' === type ) {
- type = 'gdpr-checkbox' === type ? 'checkbox' : type;
- $primary.find( 'li' ).remove();
- newChoice = '<li><input type="' + type + '" disabled>{label}</li>';
- }
- // Building an inner content for Primary field.
- var $choicesList = $( '#wpforms-field-option-row-' + id + '-choices .choices-list' ),
- $choicesToRender = $choicesList.find( 'li' ).slice( 0, 20 ),
- hasDefaults = !! $choicesList.find( 'input.default:checked' ).length,
- modernSelectChoices = [],
- showPriceAfterLabels = $( '#wpforms-field-option-' + id + '-show_price_after_labels' ).prop( 'checked' );
- $choicesToRender.each( function() {// eslint-disable-line complexity
- var $this = $( this ),
- label = wpf.sanitizeHTML( $this.find( 'input.label' ).val().trim() ),
- value = $this.find( 'input.value' ).val(),
- selected = $this.find( 'input.default' ).is( ':checked' ),
- choiceID = $this.data( 'key' ),
- $choice;
- label = label !== '' ? label : wpforms_builder.choice_empty_label_tpl.replace( '{number}', choiceID );
- label += ( showPriceAfterLabels && value ) ? ' - ' + wpf.amountFormatCurrency( value ) : '';
- // Append a new choice.
- if ( ! isModernSelect ) {
- $choice = $( newChoice.replace( /{label}/g, label ) );
- $primary.append( $choice );
- } else {
- modernSelectChoices.push(
- {
- value: label,
- label: label,
- }
- );
- }
- if ( true === selected ) {
- switch ( type ) {
- case 'select':
- if ( ! isModernSelect ) {
- $choice.prop( 'selected', 'true' );
- } else {
- modernSelectChoices[ modernSelectChoices.length - 1 ].selected = true;
- }
- break;
- case 'radio':
- case 'checkbox':
- $choice.find( 'input' ).prop( 'checked', 'true' );
- break;
- }
- }
- } );
- if ( isModernSelect ) {
- var placeholderClass = $primary.prop( 'multiple' ) ? 'input.choices__input' : '.choices__inner .choices__placeholder',
- choicesjsInstance = app.dropdownField.helpers.getInstance( $primary ),
- isDynamicChoices = $( '#wpforms-field-option-' + id + '-dynamic_choices' ).val();
- choicesjsInstance.removeActiveItems();
- choicesjsInstance.setChoices( modernSelectChoices, 'value', 'label', true );
- // Re-initialize modern dropdown to properly determine and update placeholder.
- app.dropdownField.helpers.update( id, isDynamicChoices );
- // Hide/show a placeholder for Modern select if it has or not default choices.
- $primary
- .closest( '.choices' )
- .find( placeholderClass )
- .toggleClass( 'wpforms-hidden', hasDefaults );
- }
- },
- /**
- * Field choice bulk add toggling.
- *
- * @since 1.3.7
- */
- fieldChoiceBulkAddToggle: function(el) {
- var $this = $(el),
- $label = $this.closest('label');
- if ( $this.hasClass('bulk-add-showing') ) {
- // Import details is showing, so hide/remove it
- var $selector = $label.next('.bulk-add-display');
- $selector.slideUp(400, function() {
- $selector.remove();
- });
- $this.find('span').text(wpforms_builder.bulk_add_show);
- } else {
- var importOptions = '<div class="bulk-add-display unfoldable-cont">';
- importOptions += '<p class="heading wpforms-clear">'+wpforms_builder.bulk_add_heading+' <a href="#" class="toggle-bulk-add-presets">'+wpforms_builder.bulk_add_presets_show+'</a></p>';
- importOptions += '<ul>';
- for(var key in wpforms_preset_choices) {
- importOptions += '<li><a href="#" data-preset="'+key+'" class="bulk-add-preset-insert">'+wpforms_preset_choices[key].name+'</a></li>';
- }
- importOptions += '</ul>';
- importOptions += '<textarea placeholder="' + wpforms_builder.bulk_add_placeholder + '"></textarea>';
- importOptions += '<button class="bulk-add-insert wpforms-btn wpforms-btn-sm wpforms-btn-blue">' + wpforms_builder.bulk_add_button + '</button>';
- importOptions += '</div>';
- $label.after(importOptions);
- $label.next('.bulk-add-display').slideDown(400, function() {
- $(this).find('textarea').focus();
- });
- $this.find('span').text(wpforms_builder.bulk_add_hide);
- }
- $this.toggleClass('bulk-add-showing');
- },
- /**
- * Field choice bulk insert the new choices.
- *
- * @since 1.3.7
- *
- * @param {object} el DOM element.
- */
- fieldChoiceBulkAddInsert: function( el ) {
- var $this = $( el ),
- $container = $this.closest( '.wpforms-field-option-row' ),
- $textarea = $container.find( 'textarea' ),
- $list = $container.find( '.choices-list' ),
- $choice = $list.find( 'li:first-of-type' ).clone().wrap( '<div>' ).parent(),
- choice = '',
- fieldID = $container.data( 'field-id' ),
- type = $list.data( 'field-type' ),
- nextID = Number( $list.attr( 'data-next-id' ) ),
- newValues = $textarea.val().split( '\n' ),
- newChoices = '';
- $this.prop( 'disabled', true ).html( $this.html() + ' ' + s.spinner );
- $choice.find( 'input.value,input.label' ).attr( 'value', '' );
- choice = $choice.html();
- for ( var key in newValues ) {
- if ( ! newValues.hasOwnProperty( key ) ) {
- continue;
- }
- var value = wpf.sanitizeHTML( newValues[ key ] ).trim().replace( /"/g, '"' ),
- newChoice = choice;
- newChoice = newChoice.replace( /\[choices\]\[(\d+)\]/g, '[choices][' + nextID + ']' );
- newChoice = newChoice.replace( /data-key="(\d+)"/g, 'data-key="' + nextID + '"' );
- newChoice = newChoice.replace( /value="" class="label"/g, 'value="' + value + '" class="label"' );
- // For some reasons IE has its own attribute order.
- newChoice = newChoice.replace( /class="label" type="text" value=""/g, 'class="label" type="text" value="' + value + '"' );
- newChoices += newChoice;
- nextID++;
- }
- $list.attr( 'data-next-id', nextID ).append( newChoices );
- app.fieldChoiceUpdate( type, fieldID );
- $builder.trigger( 'wpformsFieldChoiceAdd' );
- app.fieldChoiceBulkAddToggle( $container.find( '.toggle-bulk-add-display' ) );
- },
- /**
- * Toggle fields tabs (Add Fields, Field Options.
- *
- * @since 1.0.0
- */
- fieldTabToggle: function( id ) {
- $( '.wpforms-tab a' ).removeClass( 'active' );
- $( '.wpforms-field, .wpforms-title-desc' ).removeClass( 'active' );
- if ( id === 'add-fields' ) {
- $( '#add-fields a' ).addClass( 'active' );
- $( '.wpforms-field-options' ).hide();
- $( '.wpforms-add-fields' ).show();
- } else {
- $( '#field-options a' ).addClass( 'active' );
- if ( id === 'field-options' ) {
- var $field = $( '.wpforms-field' ).first();
- $field.addClass( 'active' );
- id = $field.data( 'field-id' );
- } else {
- $( '#wpforms-field-' + id ).addClass( 'active' );
- }
- $( '.wpforms-field-option' ).hide();
- $( '#wpforms-field-option-' + id ).show();
- $( '.wpforms-add-fields' ).hide();
- $( '.wpforms-field-options' ).show();
- }
- },
- /**
- * Watches fields being added and listens for a pagebreak field.
- *
- * If a pagebreak field is added, and it's the first one, then we
- * automatically add the top and bottom pagebreak elements to the
- * builder.
- *
- * @param {object} event Current DOM event.
- * @param {number} id Field ID.
- * @param {string} type Field type.
- *
- * @since 1.2.1
- */
- fieldPagebreakAdd: function( event, id, type ) {
- if ( 'pagebreak' !== type ) {
- return;
- }
- var options;
- if ( ! s.pagebreakTop ) {
- s.pagebreakTop = true;
- options = {
- position: 'top',
- scroll: false,
- defaults: {
- position: 'top',
- nav_align: 'left',
- },
- };
- app.fieldAdd( 'pagebreak', options ).done( function( res ) {
- s.pagebreakTop = res.data.field.id;
- var $preview = $( '#wpforms-field-' + res.data.field.id ),
- $options = $( '#wpforms-field-option-' + res.data.field.id );
- $options.find( '.wpforms-field-option-group' ).addClass( 'wpforms-pagebreak-top' );
- $preview.addClass( 'wpforms-field-stick wpforms-pagebreak-top' );
- } );
- } else if ( ! s.pagebreakBottom ) {
- s.pagebreakBottom = true;
- options = {
- position: 'bottom',
- scroll: false,
- defaults: {
- position: 'bottom',
- },
- };
- app.fieldAdd( 'pagebreak', options ).done( function( res ) {
- s.pagebreakBottom = res.data.field.id;
- var $preview = $( '#wpforms-field-' + res.data.field.id ),
- $options = $( '#wpforms-field-option-' + res.data.field.id );
- $options.find( '.wpforms-field-option-group' ).addClass( 'wpforms-pagebreak-bottom' );
- $preview.addClass( 'wpforms-field-stick wpforms-pagebreak-bottom' );
- } );
- }
- },
- /**
- * Watches fields being deleted and listens for a pagebreak field.
- *
- * If a pagebreak field is added, and it's the first one, then we
- * automatically add the top and bottom pagebreak elements to the
- * builder.
- *
- * @param {object} event Current DOM event.
- * @param {number} id Field ID.
- * @param {string} type Field type.
- *
- * @since 1.2.1
- */
- fieldPagebreakDelete: function( event, id, type ) {
- if ( 'pagebreak' !== type ) {
- return;
- }
- var pagebreaksRemaining = $( '.wpforms-field-pagebreak' ).not( '.wpforms-pagebreak-top, .wpforms-pagebreak-bottom' ).length;
- if ( pagebreaksRemaining ) {
- return;
- }
- // All pagebreaks, excluding top/bottom, are gone.
- // So we need to remove the top and bottom pagebreak.
- var $preview = $( '.wpforms-preview-wrap' ),
- $top = $preview.find( '.wpforms-pagebreak-top' ),
- topID = $top.data( 'field-id' ),
- $bottom = $preview.find( '.wpforms-pagebreak-bottom' ),
- bottomID = $bottom.data( 'field-id' );
- $top.remove();
- $( '#wpforms-field-option-' + topID ).remove();
- s.pagebreakTop = false;
- $bottom.remove();
- $( '#wpforms-field-option-' + bottomID ).remove();
- s.pagebreakBottom = false;
- },
- /**
- * Init Display Previous option for Pagebreak field.
- *
- * @since 1.5.8
- *
- * @param {jQuery} $field Page Break field jQuery object.
- */
- fieldPageBreakInitDisplayPrevious: function( $field ) {
- var id = $field.data( 'field-id' ),
- $prevToggle = $( '#wpforms-field-option-row-' + id + '-prev_toggle' ),
- $prev = $( '#wpforms-field-option-row-' + id + '-prev' ),
- $prevBtn = $field.find( '.wpforms-pagebreak-prev' );
- if ( $field.prevAll( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).length > 0 ) {
- $prevToggle.removeClass( 'hidden' );
- $prev.removeClass( 'hidden' );
- if ( $prevToggle.find( 'input' ).is( ':checked' ) ) {
- $prevBtn.removeClass( 'wpforms-hidden' ).text( $prev.find( 'input' ).val() );
- }
- } else {
- $prevToggle.addClass( 'hidden' );
- $prev.addClass( 'hidden' );
- $prevBtn.addClass( 'wpforms-hidden' );
- }
- },
- /**
- * Field Dynamic Choice toggle.
- *
- * @since 1.2.8
- */
- fieldDynamicChoiceToggle: function( el ) {
- var $this = $( el ),
- $thisOption = $this.parent(),
- value = $this.val(),
- id = $thisOption.data( 'field-id' ),
- type = $( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-hidden-type' ).val(),
- $field = $( '#wpforms-field-' + id ),
- $choices = $( '#wpforms-field-option-row-' + id + '-choices' ),
- $images = $( '#wpforms-field-option-' + id + '-choices_images' );
- // Hide image choices if dynamic choices is not off.
- app.fieldDynamicChoiceToggleImageChoices();
- // Fire an event when a field's dynamic choices option was changed.
- $builder.trigger( 'wpformsFieldDynamicChoiceToggle' );
- // Loading
- wpf.fieldOptionLoading( $thisOption );
- // Remove previous dynamic post type or taxonomy source options.
- $( '#wpforms-field-option-row-' + id + '-dynamic_post_type' ).remove();
- $( '#wpforms-field-option-row-' + id + '-dynamic_taxonomy' ).remove();
- /*
- * Post type or Taxonomy based dynamic populating.
- */
- if ( '' !== value ) {
- // Hide choice images option, not applicable.
- $images.addClass( 'wpforms-hidden' );
- // Hide `Bulk Add` toggle.
- $choices.find( '.toggle-bulk-add-display' ).addClass( 'wpforms-hidden' );
- var data = {
- type : value,
- field_id: id, // eslint-disable-line camelcase
- action : 'wpforms_builder_dynamic_choices',
- nonce : wpforms_builder.nonce,
- };
- $.post( wpforms_builder.ajax_url, data, function( res ) {
- if ( res.success ) {
- // New option markup.
- $thisOption.after( res.data.markup );
- } else {
- console.log( res );
- }
- // Hide loading indicator.
- wpf.fieldOptionLoading( $thisOption, true );
- // Re-init tooltips for new field.
- wpf.initTooltips();
- // Trigger Dynamic source updates.
- $( '#wpforms-field-option-' + id + '-dynamic_' + value ).find( 'option:first' ).prop( 'selected', true );
- $( '#wpforms-field-option-' + id + '-dynamic_' + value ).trigger( 'change' );
- } ).fail( function( xhr, textStatus, e ) {
- console.log( xhr.responseText );
- } );
- return; // Nothing more for dynamic populating.
- }
- /*
- * "Off" - no dynamic populating.
- */
- // Show choice images option.
- $images.removeClass( 'wpforms-hidden' );
- // Show `Bulk Add` toggle.
- $choices.find( '.toggle-bulk-add-display' ).removeClass( 'wpforms-hidden' );
- $( '#wpforms-field-' + id ).find( '.wpforms-alert' ).remove();
- if ( [ 'checkbox', 'radio', 'payment-multiple', 'payment-checkbox' ].indexOf( type ) > -1 ) {
- app.fieldChoiceUpdate( type, id );
- // Toggle elements and hide loading indicator.
- $choices.find( 'ul' ).removeClass( 'wpforms-hidden' );
- $choices.find( '.wpforms-alert' ).addClass( 'wpforms-hidden' );
- wpf.fieldOptionLoading( $thisOption, true );
- return; // Nothing more for those types.
- }
- // Get original field choices.
- var choices = [],
- $primary = $field.find( '.primary-input' ),
- key;
- $( '#wpforms-field-option-row-' + id + '-choices li' ).each( function() {
- var $this = $( this );
- choices.push( {
- label: wpf.sanitizeHTML( $this.find( '.label' ).val() ),
- selected: $this.find( '.default' ).is( ':checked' ),
- } );
- } );
- // Restore field to display original field choices.
- if ( $field.hasClass( 'wpforms-field-select' ) ) {
- var isModernSelect = app.dropdownField.helpers.isModernSelect( $primary ),
- optionHTML = '',
- selected = false;
- // Remove previous items.
- $primary.find( 'option' ).not( '.placeholder' ).remove();
- // Update Modern Dropdown.
- if ( isModernSelect && choices.length ) {
- app.dropdownField.helpers.update( id, false );
- } else {
- // Update Classic select field.
- for ( key in choices ) {
- selected = choices[ key ].selected;
- optionHTML = '<option';
- optionHTML += selected ? ' selected>' : '>';
- optionHTML += choices[ key ].label + '</option>';
- $primary.append( optionHTML );
- }
- }
- } else {
- type = 'radio';
- if ( $field.hasClass( 'wpforms-field-checkbox' ) ) {
- type = 'checkbox';
- }
- // Remove previous items.
- $primary.empty();
- // Add new items to radio or checkbox field.
- for ( key in choices ) {
- optionHTML = '<li><input type="' + type + '" disabled';
- optionHTML += choices[ key ].selected ? ' selected>' : '>';
- optionHTML += choices[ key ].label + '</li>';
- $primary.append( optionHTML );
- }
- }
- // Toggle elements and hide loading indicator.
- $choices.find( 'ul' ).removeClass( 'wpforms-hidden' );
- $choices.find( '.wpforms-alert' ).addClass( 'wpforms-hidden' );
- wpf.fieldOptionLoading( $thisOption, true );
- },
- /**
- * Field Dynamic Choice Source toggle.
- *
- * @since 1.2.8
- */
- fieldDynamicChoiceSource: function( el ) {
- var $this = $( el ),
- $thisOption = $this.parent(),
- value = $this.val(),
- id = $thisOption.data( 'field-id' ),
- form_id = $( '#wpforms-builder-form' ).data( 'id' ),
- $choices = $( '#wpforms-field-option-row-' + id + '-choices' ),
- $field = $( '#wpforms-field-' + id ),
- type = $( '#wpforms-field-option-' + id + '-dynamic_choices option:selected' ).val(),
- limit = 20;
- // Loading.
- wpf.fieldOptionLoading( $thisOption );
- var data = {
- type : type,
- source : value,
- field_id: id,
- form_id : form_id,
- action : 'wpforms_builder_dynamic_source',
- nonce : wpforms_builder.nonce
- };
- $.post( wpforms_builder.ajax_url, data, function( res ) {
- if ( ! res.success ) {
- console.log( res );
- // Toggle elements and hide loading indicator.
- wpf.fieldOptionLoading( $thisOption, true );
- return;
- }
- // Update info box and remove old choices.
- $choices.find( '.dynamic-name' ).text( res.data.source_name );
- $choices.find( '.dynamic-type' ).text( res.data.type_name );
- $choices.find( 'ul' ).addClass( 'wpforms-hidden' );
- $choices.find( '.wpforms-alert' ).removeClass( 'wpforms-hidden' );
- // Update items.
- app.fieldDynamicChoiceSourceItems( $field, res.data.items );
- if ( $field.hasClass( 'wpforms-field-select' ) ) {
- limit = 200;
- }
- // If the source has more items than the field type can
- // ideally handle alert the user.
- if ( Number( res.data.total ) > limit ) {
- var msg = wpforms_builder.dynamic_choice_limit;
- msg = msg.replace( '{source}', res.data.source_name );
- msg = msg.replace( '{type}', res.data.type_name );
- msg = msg.replace( '{limit}', limit );
- msg = msg.replace( '{total}', res.data.total );
- $.alert( {
- title: wpforms_builder.heads_up,
- content: msg,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- }
- // Toggle limit choices alert message.
- app.firstNChoicesAlert( id, res.data.total );
- // Toggle elements and hide loading indicator.
- wpf.fieldOptionLoading( $thisOption, true );
- } ).fail( function( xhr, textStatus, e ) {
- console.log( xhr.responseText );
- } );
- },
- /**
- * Update a Field Items when `Dynamic Choice` Source is toggled.
- *
- * @since 1.6.1
- *
- * @param {object} $field jQuery selector for current field.
- * @param {object} items Items collection.
- */
- fieldDynamicChoiceSourceItems: function( $field, items ) {
- var $primary = $field.find( '.primary-input' ),
- key = 0;
- if ( $field.hasClass( 'wpforms-field-select' ) ) {
- var isModernSelect = app.dropdownField.helpers.isModernSelect( $primary );
- if ( isModernSelect ) {
- app.fieldDynamicChoiceSourceForModernSelect( $primary, items );
- } else {
- app.fieldDynamicChoiceSourceForClassicSelect( $primary, items );
- }
- } else {
- var type = 'radio';
- if ( $field.hasClass( 'wpforms-field-checkbox' ) ) {
- type = 'checkbox';
- }
- // Remove previous items.
- $primary.empty();
- // Add new items to radio or checkbox field.
- for ( key in items ) {
- $primary.append( '<li><input type="' + type + '" disabled> ' + wpf.sanitizeHTML( items[ key ] ) + '</li>' );
- }
- }
- },
- /**
- * Update options for Modern style select when `Dynamic Choice` Source is toggled.
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery selector for primary input.
- * @param {object} items Items collection.
- */
- fieldDynamicChoiceSourceForModernSelect: function( $jquerySelector, items ) {
- var instance = app.dropdownField.helpers.getInstance( $jquerySelector ),
- fieldId = $jquerySelector.closest( '.wpforms-field' ).data().fieldId;
- // Destroy the instance of Choices.js.
- instance.destroy();
- // Update a placeholder.
- app.dropdownField.helpers.updatePlaceholderChoice( instance, fieldId );
- // Update options.
- app.fieldDynamicChoiceSourceForClassicSelect( $jquerySelector, items );
- // Choices.js init.
- app.dropdownField.events.choicesInit( $jquerySelector );
- },
- /**
- * Update options for Classic style select when `Dynamic Choice` Source is toggled.
- *
- * @since 1.6.1
- *
- * @param {object} $jquerySelector jQuery selector for primary input.
- * @param {object} items Items collection.
- */
- fieldDynamicChoiceSourceForClassicSelect: function( $jquerySelector, items ) {
- var index = 0,
- itemsSize = items.length;
- // Clear.
- $jquerySelector.find( 'option' ).not( '.placeholder' ).remove();
- // Add options (items) to a single <select> field.
- for ( ; index < itemsSize; index++ ) {
- var item = wpf.sanitizeHTML( items[ index ] );
- $jquerySelector.append( '<option value="' + item + '">' + item + '</option>' );
- }
- },
- /**
- * Image choice toggle, hide image choices, image choices style, choices if Dynamic choices is not OFF.
- *
- * @since 1.5.8
- */
- fieldDynamicChoiceToggleImageChoices: function() {
- $( '#wpforms-builder .wpforms-field-options .wpforms-field-option' ).each(
- function( key, value ) {
- var $option = $( value ),
- dynamicSelect = $option.find( '.wpforms-field-option-row-dynamic_choices select' );
- if (
- typeof dynamicSelect.val() !== 'undefined' &&
- '' !== dynamicSelect.val()
- ) {
- $option.find( '.wpforms-field-option-row-choices_images' ).hide();
- $option.find( '.wpforms-field-option-row-choices_images_style' ).hide();
- } else {
- $option.find( '.wpforms-field-option-row-choices_images' ).show();
- $option.find( '.wpforms-field-option-row-choices_images_style' ).show();
- }
- }
- );
- },
- /**
- * Show choices limit alert message.
- *
- * @since 1.6.9
- *
- * @param {number} fieldId Field ID.
- * @param {number} total Total number of choices.
- */
- firstNChoicesAlert: function( fieldId, total ) {
- var tmpl = wp.template( 'wpforms-choices-limit-message' ),
- data = {
- total: total,
- },
- limit = 20,
- $field = $( '#wpforms-field-' + fieldId );
- // Don't show message for select fields.
- if ( $field.hasClass( 'wpforms-field-select' ) ) {
- return;
- }
- $field.find( '.wpforms-alert-dynamic' ).remove();
- if ( total > limit ) {
- $field.find( '.primary-input' ).after( tmpl( data ) );
- }
- },
- /**
- * Field layout selector toggling.
- *
- * @since 1.3.7
- */
- fieldLayoutSelectorToggle: function(el) {
- var $this = $(el),
- $label = $this.closest('label'),
- layouts = {
- 'layout-1' : [
- {
- 'class': 'one-half',
- 'data' : 'wpforms-one-half wpforms-first'
- },
- {
- 'class': 'one-half',
- 'data' : 'wpforms-one-half'
- }
- ],
- 'layout-2' : [
- {
- 'class': 'one-third',
- 'data' : 'wpforms-one-third wpforms-first'
- },
- {
- 'class': 'one-third',
- 'data' : 'wpforms-one-third'
- },
- {
- 'class': 'one-third',
- 'data' : 'wpforms-one-third'
- }
- ],
- 'layout-3' : [
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth wpforms-first'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- }
- ],
- 'layout-4' : [
- {
- 'class': 'one-third',
- 'data' : 'wpforms-one-third wpforms-first'
- },
- {
- 'class': 'two-third',
- 'data' : 'wpforms-two-thirds'
- }
- ],
- 'layout-5' : [
- {
- 'class': 'two-third',
- 'data' : 'wpforms-two-thirds wpforms-first'
- },
- {
- 'class': 'one-third',
- 'data' : 'wpforms-one-third'
- }
- ],
- 'layout-6' : [
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth wpforms-first'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- },
- {
- 'class': 'two-fourth',
- 'data' : 'wpforms-two-fourths'
- }
- ],
- 'layout-7' : [
- {
- 'class': 'two-fourth',
- 'data' : 'wpforms-two-fourths wpforms-first'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- }
- ],
- 'layout-8' : [
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth wpforms-first'
- },
- {
- 'class': 'two-fourth',
- 'data' : 'wpforms-two-fourths'
- },
- {
- 'class': 'one-fourth',
- 'data' : 'wpforms-one-fourth'
- }
- ]
- };
- if ( $this.hasClass('layout-selector-showing') ) {
- // Selector is showing, so hide/remove it
- var $selector = $label.next('.layout-selector-display');
- $selector.slideUp(400, function() {
- $selector.remove();
- });
- $this.find('span').text(wpforms_builder.layout_selector_show);
- } else {
- // Create selector options
- var layoutOptions = '<div class="layout-selector-display unfoldable-cont">';
- layoutOptions += '<p class="heading">' + wpforms_builder.layout_selector_layout + '</p>';
- layoutOptions += '<div class="layouts">';
- for ( var key in layouts ) {
- var layout = layouts[ key ];
- layoutOptions += '<div class="layout-selector-display-layout">';
- for ( var i in layout ) {
- layoutOptions += '<span class="' + layout[ i ].class + '" data-classes="' + layout[ i ].data + '"></span>';
- }
- layoutOptions += '</div>';
- }
- layoutOptions += '</div></div>';
- $label.after( layoutOptions );
- $label.next( '.layout-selector-display' ).slideDown();
- $this.find( 'span' ).text( wpforms_builder.layout_selector_hide );
- }
- $this.toggleClass( 'layout-selector-showing' );
- },
- /**
- * Field layout selector, selecting a layout.
- *
- * @since 1.3.7
- */
- fieldLayoutSelectorLayout: function(el) {
- var $this = $(el),
- $label = $this.closest('label');
- $this.parent().find('.layout-selector-display-layout').not($this).remove();
- $this.parent().find('.heading').text(wpforms_builder.layout_selector_column);
- $this.toggleClass('layout-selector-display-layout layout-selector-display-columns')
- },
- /**
- * Field layout selector, insert into class field.
- *
- * @since 1.3.7
- */
- fieldLayoutSelectorInsert: function(el) {
- var $this = $(el),
- $selector = $this.closest('.layout-selector-display'),
- $parent = $selector.parent(),
- $label = $parent.find('label'),
- $input = $parent.find('input[type=text]'),
- classes = $this.data('classes');
- if ( $input.val() ) {
- classes = ' ' + classes;
- }
- $input.insertAtCaret(classes);
- // remove list, all done!
- $selector.slideUp(400, function() {
- $selector.remove();
- });
- $label.find('.toggle-layout-selector-display').removeClass('layout-selector-showing');
- $label.find('.toggle-layout-selector-display span').text(wpforms_builder.layout_selector_show);
- },
- //--------------------------------------------------------------------//
- // Settings Panel
- //--------------------------------------------------------------------//
- /**
- * Element bindings for Settings panel.
- *
- * @since 1.0.0
- */
- bindUIActionsSettings: function() {
- // Clicking form title/desc opens Settings panel.
- $builder.on( 'click', '.wpforms-title-desc, .wpforms-field-submit-button, .wpforms-center-form-name', function( e ) {
- e.preventDefault();
- app.panelSwitch( 'settings' );
- if ( $( this ).hasClass( 'wpforms-center-form-name' ) || $( this ).hasClass( 'wpforms-title-desc' ) ) {
- setTimeout( function() {
- $( '#wpforms-panel-field-settings-form_title' ).focus();
- }, 300 );
- }
- } );
- // Clicking form previous page break button.
- $builder.on( 'click', '.wpforms-field-pagebreak-last button', function( e ) {
- e.preventDefault();
- app.panelSwitch( 'settings' );
- $( '#wpforms-panel-field-settings-pagebreak_prev' ).focus();
- } );
- // Clicking form last page break button.
- $builder.on( 'input', '#wpforms-panel-field-settings-pagebreak_prev', function() {
- $( '.wpforms-field-pagebreak-last button' ).text( $( this ).val() );
- } );
- // Real-time updates for editing the form title.
- $builder.on( 'input', '#wpforms-panel-field-settings-form_title, #wpforms-setup-name', function() {
- var title = $.trim( $( this ).val() );
- $( '.wpforms-preview .wpforms-form-name' ).text( title );
- $( '.wpforms-center-form-name.wpforms-form-name' ).text( title );
- app.trimFormTitle();
- } );
- // Real-time updates for editing the form description.
- $builder.on( 'input', '#wpforms-panel-field-settings-form_desc', function() {
- $( '.wpforms-form-desc' ).text( $( this ).val() );
- } );
- // Real-time updates for editing the form submit button.
- $builder.on( 'input', '#wpforms-panel-field-settings-submit_text', function() {
- $( '.wpforms-field-submit input[type=submit]' ).val( $( this ).val() );
- } );
- // Toggle form reCAPTCHA setting.
- $builder.on( 'change', '#wpforms-panel-field-settings-recaptcha', function() {
- app.captchaToggle();
- } );
- // Toggle form confirmation setting fields.
- $builder.on( 'change', '.wpforms-panel-field-confirmations-type', function() {
- app.confirmationFieldsToggle( $( this ) );
- } );
- $builder.on( 'change', '.wpforms-panel-field-confirmations-message_entry_preview', app.confirmationEntryPreviewToggle );
- // Toggle form notification setting fields.
- $builder.on( 'change', '#wpforms-panel-field-settings-notification_enable', function() {
- app.notificationToggle();
- } );
- // Add new settings block.
- $builder.on( 'click', '.wpforms-builder-settings-block-add', function( e ) {
- e.preventDefault();
- if ( ! wpforms_builder.pro ) {
- return;
- }
- app.settingsBlockAdd( $( this ) );
- } );
- // Edit settings block name.
- $builder.on( 'click', '.wpforms-builder-settings-block-edit', function( e ) {
- e.preventDefault();
- var $el = $( this );
- if ( $el.parents( '.wpforms-builder-settings-block-header' ).find( '.wpforms-builder-settings-block-name' ).hasClass( 'editing' ) ) {
- app.settingsBlockNameEditingHide( $el );
- } else {
- app.settingsBlockNameEditingShow( $el );
- }
- } );
- // Update settings block name and close editing interface.
- $builder.on( 'blur', '.wpforms-builder-settings-block-name-edit input', function( e ) {
- // Do not fire if for onBlur user clicked on edit button - it has own event processing.
- if ( ! $( e.relatedTarget ).hasClass( 'wpforms-builder-settings-block-edit' ) ) {
- app.settingsBlockNameEditingHide( $( this ) );
- }
- } );
- // Close settings block editing interface with pressed Enter.
- $builder.on( 'keypress', '.wpforms-builder-settings-block-name-edit input', function( e ) {
- // On Enter - hide editing interface.
- if ( e.keyCode === 13 ) {
- app.settingsBlockNameEditingHide( $( this ) );
- // We need this preventDefault() to stop jumping to form name editing input.
- e.preventDefault();
- }
- } );
- // Clone settings block.
- $builder.on( 'click', '.wpforms-builder-settings-block-clone', function( e ) {
- e.preventDefault();
- app.settingsBlockPanelClone( $( this ) );
- } );
- // Toggle settings block - slide up or down.
- $builder.on( 'click', '.wpforms-builder-settings-block-toggle', function( e ) {
- e.preventDefault();
- app.settingsBlockPanelToggle( $( this ) );
- } );
- // Remove settings block.
- $builder.on( 'click', '.wpforms-builder-settings-block-delete', function( e ) {
- e.preventDefault();
- app.settingsBlockDelete( $( this ) );
- } );
- },
- /**
- * Toggle displaying the CAPTCHA.
- *
- * @since 1.6.4
- */
- captchaToggle: function() {
- var $preview = $builder.find( '.wpforms-field-recaptcha' ),
- $setting = $( '#wpforms-panel-field-settings-recaptcha' ),
- provider = $setting.data( 'provider' );
- provider = provider || 'recaptcha';
- if ( ! $preview.length ) {
- return;
- }
- if ( $setting.is( ':checked' ) ) {
- $preview
- .show()
- .toggleClass( 'is-recaptcha', 'recaptcha' === provider );
- } else {
- $preview.hide();
- }
- },
- /**
- * Setup the Confirmation blocks.
- *
- * @since 1.4.8
- */
- confirmationsSetup: function() {
- // Toggle the setting fields in each confirmation block.
- $( '.wpforms-panel-field-confirmations-type' ).each( function() {
- app.confirmationFieldsToggle( $( this ) );
- } );
- // Init TinyMCE in each confirmation block.
- $( '.wpforms-panel-field-confirmations-message' ).each( function() {
- if ( typeof tinymce !== 'undefined' && typeof wp.editor !== 'undefined' ) {
- wp.editor.initialize( $( this ).attr( 'id' ), s.tinymceDefaults );
- }
- } );
- // Validate Confirmation Redirect URL.
- $builder.on( 'focusout', '.wpforms-panel-field-confirmations-redirect', function( event ) {
- var $field = $( this ),
- url = $field.val().trim();
- $field.val( url );
- if ( wpf.isURL( url ) || url === '' ) {
- return;
- }
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.redirect_url_field_error,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- $field.focus();
- },
- },
- },
- } );
- } );
- },
- /**
- * Toggle the different form Confirmation setting fields.
- *
- * @since 1.4.8
- *
- * @param {jQuery} $el Element.
- */
- confirmationFieldsToggle: function( $el ) {
- if ( ! $el.length ) {
- return;
- }
- var type = $el.val(),
- $block = $el.closest( '.wpforms-builder-settings-block-content' );
- $block.find( '.wpforms-panel-field' )
- .not( $el.parent() )
- .not( '.wpforms-conditionals-enable-toggle' )
- .hide();
- $block.find( '.wpforms-panel-field-confirmations-' + type ).closest( '.wpforms-panel-field' ).show();
- if ( type === 'message' ) {
- $block.find( '.wpforms-panel-field-confirmations-message_scroll' ).closest( '.wpforms-panel-field' ).show();
- $block.find( '.wpforms-panel-field-confirmations-message_entry_preview' ).trigger( 'change' ).closest( '.wpforms-panel-field' ).show();
- }
- },
- /**
- * Show/hide an entry preview message.
- *
- * @since 1.6.9
- */
- confirmationEntryPreviewToggle: function() {
- var $this = $( this ),
- $styleField = $this.closest( '.wpforms-builder-settings-block-content' ).find( '.wpforms-panel-field-confirmations-message_entry_preview_style' ).parent();
- $this.is( ':checked' ) ? $styleField.show() : $styleField.hide();
- },
- /**
- * Toggle the displaying notification settings depending on if the
- * notifications are enabled.
- *
- * @since 1.1.9
- */
- notificationToggle: function() {
- var $notification = $( '#wpforms-panel-field-settings-notification_enable' ),
- $settingsBlock = $notification.closest( '.wpforms-panel-content-section' ).find( '.wpforms-builder-settings-block' ),
- $enabled = $notification.is( ':checked' );
- // Toggle Add new notification button.
- $( '.wpforms-notifications-add' ).toggleClass( 'wpforms-hidden', ! $enabled );
- $enabled ? $settingsBlock.show() : $settingsBlock.hide();
- },
- /**
- * Notifications by status alerts.
- *
- * @since 1.6.6
- */
- notificationsByStatusAlerts: function() {
- $builder.on( 'change', '.wpforms-panel-content-section-notifications .wpforms-notification-by-status-alert', function( e ) {
- var $input = $( this );
- if ( ! $input.prop( 'checked' ) ) {
- return;
- }
- var $enabled = $( '.wpforms-radio-group-' + $input.attr( 'data-radio-group' ) + ':checked:not(#' + $input.attr( 'id' ) + ')' ),
- alertText = '';
- if ( $enabled.length === 0 ) {
- alertText = wpforms_builder.notification_by_status_enable_alert;
- alertText = alertText.replace( /%s/g, $input.data( 'provider-title' ) );
- } else {
- alertText = wpforms_builder.notification_by_status_switch_alert;
- alertText = alertText.replace( /%2\$s/g, $enabled.data( 'provider-title' ) );
- alertText = alertText.replace( /%1\$s/g, $input.data( 'provider-title' ) );
- }
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: alertText,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- },
- },
- } );
- } );
- },
- /**
- * Add new settings block.
- *
- * @since 1.4.8
- * @since 1.6.1 Added processing for Field Map table.
- * @since 1.6.1.2 Registered `wpformsSettingsBlockAdded` trigger.
- *
- * @param {jQuery} $el Settings Block jQuery object.
- */
- settingsBlockAdd: function($el) {
- var nextID = Number( $el.attr( 'data-next-id' ) ),
- panelID = $el.closest( '.wpforms-panel-content-section' ).data( 'panel' ),
- blockType = $el.data( 'block-type' ),
- namePrompt = wpforms_builder[ blockType + '_prompt' ],
- nameField = '<input autofocus="" type="text" id="settings-block-name" placeholder="' + wpforms_builder[ blockType + '_ph' ] + '">',
- nameError = '<p class="error">' + wpforms_builder[ blockType + '_error' ] + '</p>',
- modalContent = namePrompt + nameField + nameError;
- var modal = $.confirm( {
- container: $builder,
- title: false,
- content: modalContent,
- icon: 'fa fa-info-circle',
- type: 'blue',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- var settingsBlockName = $.trim( this.$content.find( 'input#settings-block-name' ).val() ),
- error = this.$content.find( '.error' );
- if ( settingsBlockName === '' ) {
- error.show();
- return false;
- } else {
- var $firstSettingsBlock = $el.closest( '.wpforms-panel-content-section' ).find( '.wpforms-builder-settings-block' ).first();
- // Restore tooltips before cloning.
- wpf.restoreTooltips( $firstSettingsBlock );
- var $newSettingsBlock = $firstSettingsBlock.clone(),
- blockID = $firstSettingsBlock.data( 'block-id' ),
- newSettingsBlock;
- $newSettingsBlock.attr( 'data-block-id', nextID );
- $newSettingsBlock.find( '.wpforms-builder-settings-block-header span' ).text( settingsBlockName );
- $newSettingsBlock.find( 'input, textarea, select' ).not( '.from-name input' ).not( '.from-email input' ).each( function( index, el ) {
- var $this = $( this );
- if ( $this.attr( 'name' ) ) {
- $this.val( '' ).attr( 'name', $this.attr( 'name' ).replace( /\[(\d+)\]/, '[' + nextID + ']' ) );
- if ( $this.is( 'select' ) ) {
- $this.find( 'option' ).prop( 'selected', false ).attr( 'selected', false );
- $this.find( 'option:first' ).prop( 'selected', true ).attr( 'selected', 'selected' );
- } else if ( $this.attr( 'type' ) === 'checkbox' ) {
- $this.prop( 'checked', false ).attr( 'checked', false ).val( '1' );
- } else {
- $this.val( '' ).attr( 'value', '' );
- }
- }
- } );
- // Update elements IDs.
- var idPrefixPanel = 'wpforms-panel-field-' + panelID + '-',
- idPrefixBlock = idPrefixPanel + blockID;
- $newSettingsBlock.find( '[id^="' + idPrefixBlock + '"], [for^="' + idPrefixBlock + '"]' ).each( function( index, el ) {
- var $el = $( this ),
- attr = $el.prop( 'tagName' ) === 'LABEL' ? 'for' : 'id',
- elID = $el.attr( attr ).replace( new RegExp( idPrefixBlock, 'g' ), idPrefixPanel + nextID );
- $el.attr( attr, elID );
- } );
- // Update `notification by status` checkboxes.
- var radioGroup = blockID + '-notification-by-status';
- $newSettingsBlock.find( '[data-radio-group="' + radioGroup + '"]' ).each( function( index, el ) {
- $( this )
- .removeClass( 'wpforms-radio-group-' + radioGroup )
- .addClass( 'wpforms-radio-group-' + nextID + '-notification-by-status' )
- .attr( 'data-radio-group', nextID + '-notification-by-status' );
- } );
- $newSettingsBlock.find( '.wpforms-builder-settings-block-header input' ).val( settingsBlockName ).attr( 'value', settingsBlockName );
- if ( blockType === 'notification' ) {
- $newSettingsBlock.find( '.email-msg textarea' ).val( '{all_fields}' ).attr( 'value', '{all_fields}' );
- $newSettingsBlock.find( '.email-recipient input' ).val( '{admin_email}' ).attr( 'value', '{admin_email}' );
- }
- $newSettingsBlock.removeClass( 'wpforms-builder-settings-block-default' );
- if ( blockType === 'confirmation' ) {
- $newSettingsBlock.find( '.wpforms-panel-field-tinymce' ).remove();
- if ( typeof WPForms !== 'undefined' ) {
- $newSettingsBlock.find( '.wpforms-panel-field-confirmations-type-wrap' )
- .after( WPForms.Admin.Builder.Templates
- .get( 'wpforms-builder-confirmations-message-field' )( {
- id: nextID,
- } )
- );
- }
- }
- // Conditional logic, if present
- var $conditionalLogic = $newSettingsBlock.find( '.wpforms-conditional-block' );
- if ( $conditionalLogic.length && typeof WPForms !== 'undefined' ) {
- $conditionalLogic
- .html( WPForms.Admin.Builder.Templates
- .get( 'wpforms-builder-conditional-logic-toggle-field' )( {
- id: nextID,
- type: blockType,
- actions: JSON.stringify( $newSettingsBlock.find( '.wpforms-panel-field-conditional_logic-checkbox' ).data( 'actions' ) ),
- actionDesc: $newSettingsBlock.find( '.wpforms-panel-field-conditional_logic-checkbox' ).data( 'action-desc' ),
- } )
- );
- }
- // Fields Map Table, if present.
- var $fieldsMapTable = $newSettingsBlock.find( '.wpforms-field-map-table' );
- if ( $fieldsMapTable.length ) {
- $fieldsMapTable.each( function( index, el ) {
- var $table = $( el );
- // Clean table fields.
- $table.find( 'tr:not(:first-child)' ).remove();
- var $input = $table.find( '.key input' ),
- $select = $table.find( '.field select' ),
- name = $select.data( 'name' );
- $input.attr( 'value', '' );
- $select
- .attr( 'name', '' )
- .attr( 'data-name', name.replace( /\[(\d+)\]/, '[' + nextID + ']' ) );
- } );
- }
- newSettingsBlock = $newSettingsBlock.wrap( '<div>' ).parent().html();
- newSettingsBlock = newSettingsBlock.replace( /\[conditionals\]\[(\d+)\]\[(\d+)\]/g, '[conditionals][0][0]' );
- $firstSettingsBlock.before( newSettingsBlock );
- var $addedSettingBlock = $firstSettingsBlock.prev();
- // Reset the confirmation type to the 1st one.
- if ( blockType === 'confirmation' ) {
- app.confirmationFieldsToggle( $( '.wpforms-panel-field-confirmations-type' ).first() );
- }
- // Init the WP Editor.
- if ( typeof tinymce !== 'undefined' && typeof wp.editor !== 'undefined' && blockType === 'confirmation' ) {
- wp.editor.initialize( 'wpforms-panel-field-confirmations-message-' + nextID, s.tinymceDefaults );
- }
- // Init tooltips for new section.
- wpf.initTooltips();
- $builder.trigger( 'wpformsSettingsBlockAdded', [ $addedSettingBlock ] );
- $el.attr( 'data-next-id', nextID + 1 );
- }
- },
- },
- cancel: {
- text: wpforms_builder.cancel,
- },
- },
- } );
- // We need to process this event here, because we need a confirm modal object defined, so we can intrude into it.
- // Pressing Enter will click the Ok button.
- $builder.on( 'keypress', '#settings-block-name', function( e ) {
- if ( e.keyCode === 13 ) {
- $( modal.buttons.confirm.el ).trigger( 'click' );
- }
- } );
- },
- /**
- * Show settings block editing interface.
- *
- * @since 1.4.8
- */
- settingsBlockNameEditingShow: function ($el) {
- var header_holder = $el.parents('.wpforms-builder-settings-block-header'),
- name_holder = header_holder.find('.wpforms-builder-settings-block-name');
- name_holder
- .addClass('editing')
- .hide();
- // Make the editing interface active and in focus
- header_holder.find('.wpforms-builder-settings-block-name-edit').addClass('active');
- wpf.focusCaretToEnd(header_holder.find('input'));
- },
- /**
- * Update settings block name and hide editing interface.
- *
- * @since 1.4.8
- */
- settingsBlockNameEditingHide: function ($el) {
- var header_holder = $el.parents('.wpforms-builder-settings-block-header'),
- name_holder = header_holder.find('.wpforms-builder-settings-block-name'),
- edit_holder = header_holder.find('.wpforms-builder-settings-block-name-edit'),
- current_name = edit_holder.find('input').val().trim(),
- blockType = $el.closest('.wpforms-builder-settings-block').data('block-type');
- // Provide a default value for empty settings block name.
- if (! current_name.length) {
- current_name = wpforms_builder[blockType + '_def_name'];
- }
- // This is done for sanitizing.
- edit_holder.find('input').val(current_name);
- name_holder.text(current_name);
- // Editing should be hidden, displaying - active.
- name_holder
- .removeClass('editing')
- .show();
- edit_holder.removeClass('active');
- },
- /**
- * Clone the Notification block with all of its content and events.
- * Put the newly created clone above the target.
- *
- * @since 1.6.5
- *
- * @param {object} $el Clone icon DOM element.
- */
- settingsBlockPanelClone: function( $el ) {
- var $panel = $el.closest( '.wpforms-panel-content-section' ),
- $addNewSettingButton = $panel.find( '.wpforms-builder-settings-block-add' ),
- $settingsBlock = $el.closest( '.wpforms-builder-settings-block' ),
- $settingBlockContent = $settingsBlock.find( '.wpforms-builder-settings-block-content' ),
- settingsBlockId = parseInt( $addNewSettingButton.attr( 'data-next-id' ), 10 ),
- settingsBlockType = $settingsBlock.data( 'block-type' ),
- settingsBlockName = $settingsBlock.find( '.wpforms-builder-settings-block-name' ).text().trim() + wpforms_builder[ settingsBlockType + '_clone' ],
- isVisibleContent = $settingBlockContent.is( ':hidden' );
- // Restore tooltips before cloning.
- wpf.restoreTooltips( $settingsBlock );
- var $clone = $settingsBlock.clone( false, true );
- // Save open/close state while cloning.
- app.settingsBlockUpdateState( isVisibleContent, settingsBlockId, settingsBlockType );
- // Change the cloned setting block ID and name.
- $clone.data( 'block-id', settingsBlockId );
- $clone.find( '.wpforms-builder-settings-block-header span' ).text( settingsBlockName );
- $clone.find( '.wpforms-builder-settings-block-header input' ).val( settingsBlockName );
- $clone.removeClass( 'wpforms-builder-settings-block-default' );
- // Change the Next Settings block ID for "Add new" button.
- $addNewSettingButton.attr( 'data-next-id', settingsBlockId + 1 );
- // Change the name attribute.
- $clone.find( 'input, textarea, select' ).each( function() {
- var $this = $( this );
- if ( $this.attr( 'name' ) ) {
- $this.attr( 'name', $this.attr( 'name' ).replace( /\[(\d+)\]/, '[' + settingsBlockId + ']' ) );
- }
- if ( $this.data( 'name' ) ) {
- $this.data( 'name', $this.data( 'name' ).replace( /\[(\d+)\]/, '[' + settingsBlockId + ']' ) );
- }
- if ( $this.attr( 'class' ) ) {
- $this.attr( 'class', $this.attr( 'class' ).replace( /-(\d+)/, '-' + settingsBlockId ) );
- }
- if ( $this.attr( 'data-radio-group' ) ) {
- $this.attr( 'data-radio-group', $this.attr( 'data-radio-group' ).replace( /(\d+)-/, settingsBlockId + '-' ) );
- }
- } );
- // Change IDs/data-attributes in DOM elements.
- $clone.find( '*' ).each( function() {
- var $this = $( this );
- if ( $this.attr( 'id' ) ) {
- $this.attr( 'id', $this.attr( 'id' ).replace( /-(\d+)/, '-' + settingsBlockId ) );
- }
- if ( $this.attr( 'for' ) ) {
- $this.attr( 'for', $this.attr( 'for' ).replace( /-(\d+)-/, '-' + settingsBlockId + '-' ) );
- }
- if ( $this.data( 'input-name' ) ) {
- $this.data( 'input-name', $this.data( 'input-name' ).replace( /\[(\d+)\]/, '[' + settingsBlockId + ']' ) );
- }
- } );
- // Transfer selected values to copied elements since jQuery doesn't clone the current selected state.
- $settingsBlock.find( 'select' ).each( function() {
- var baseSelectName = $( this ).attr( 'name' ),
- clonedSelectName = $( this ).attr( 'name' ).replace( /\[(\d+)\]/, '[' + settingsBlockId + ']' );
- $clone.find( 'select[name="' + clonedSelectName + '"]' ).val( $( this ).attr( 'name', baseSelectName ).val() );
- } );
- // Insert before the target settings block.
- $clone
- .css( 'display', 'none' )
- .insertBefore( $settingsBlock )
- .show( 'fast', function() {
- // Init tooltips for new section.
- wpf.initTooltips();
- } );
- },
- /**
- * Show or hide settings block panel content.
- *
- * @since 1.4.8
- *
- * @param {object} $el Toggle icon DOM element.
- */
- settingsBlockPanelToggle: function( $el ) {
- var $settingsBlock = $el.closest( '.wpforms-builder-settings-block' ),
- settingsBlockId = $settingsBlock.data( 'block-id' ),
- settingsBlockType = $settingsBlock.data( 'block-type' ),
- $content = $settingsBlock.find( '.wpforms-builder-settings-block-content' ),
- isVisible = $content.is( ':visible' );
- $content.stop().slideToggle( {
- duration: 400,
- start: function() {
- // Send early to save fast.
- // It's animation start, so we should save the state for animation end (reversed).
- app.settingsBlockUpdateState( isVisible, settingsBlockId, settingsBlockType );
- },
- always: function() {
- if ( $content.is( ':visible' ) ) {
- $el.html( '<i class="fa fa-chevron-circle-up"></i>' );
- } else {
- $el.html( '<i class="fa fa-chevron-circle-down"></i>' );
- }
- },
- } );
- },
- /**
- * Delete settings block.
- *
- * @since 1.4.8
- * @since 1.6.1.2 Registered `wpformsSettingsBlockDeleted` trigger.
- *
- * @param {jQuery} $el Delete button element.
- */
- settingsBlockDelete: function( $el ) {
- var $contentSection = $el.closest( '.wpforms-panel-content-section' ),
- $currentBlock = $el.closest( '.wpforms-builder-settings-block' ),
- blockType = $currentBlock.data( 'block-type' );
- // Skip if only one block persist.
- // This condition should not execute in normal circumstances.
- if ( $contentSection.find( '.wpforms-builder-settings-block' ).length < 2 ) {
- return;
- }
- $.confirm( {
- title: false,
- content: wpforms_builder[ blockType + '_delete' ],
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function() {
- var settingsBlockId = $currentBlock.data( 'block-id' ),
- settingsBlockType = $currentBlock.data( 'block-type' );
- /* eslint-disable camelcase */
- $.post( wpforms_builder.ajax_url, {
- action : 'wpforms_builder_settings_block_state_remove',
- nonce : wpforms_builder.nonce,
- block_id : settingsBlockId,
- block_type: settingsBlockType,
- form_id : s.formID,
- } );
- /* eslint-enable */
- $currentBlock.remove();
- $builder.trigger( 'wpformsSettingsBlockDeleted', [ blockType, settingsBlockId ] );
- },
- },
- cancel: {
- text: wpforms_builder.cancel,
- },
- },
- } );
- },
- /**
- * Change open/close state for setting block.
- *
- * @since 1.6.5
- *
- * @param {boolean} isVisible State status.
- * @param {number} settingsBlockId Block ID.
- * @param {string} settingsBlockType Block type.
- *
- */
- settingsBlockUpdateState: function( isVisible, settingsBlockId, settingsBlockType ) {
- $.post( wpforms_builder.ajax_url, {
- action: 'wpforms_builder_settings_block_state_save',
- state: isVisible ? 'closed' : 'opened',
- form_id: s.formID,
- block_id: settingsBlockId,
- block_type: settingsBlockType,
- nonce: wpforms_builder.nonce,
- } );
- },
- //--------------------------------------------------------------------//
- // Save and Exit
- //--------------------------------------------------------------------//
- /**
- * Element bindings for Embed and Save/Exit items.
- *
- * @since 1.0.0
- * @since 1.5.8 Added trigger on `wpformsSaved` event to remove a `newform` URL-parameter.
- */
- bindUIActionsSaveExit: function() {
- // Embed form.
- $builder.on( 'click', '#wpforms-embed', function( e ) {
- e.preventDefault();
- if ( $( this ).hasClass( 'wpforms-disabled' ) ) {
- return;
- }
- WPFormsFormEmbedWizard.openPopup();
- } );
- // Save form.
- $builder.on( 'click', '#wpforms-save', function( e ) {
- e.preventDefault();
- app.formSave( false );
- } );
- // Exit builder.
- $builder.on( 'click', '#wpforms-exit', function( e ) {
- e.preventDefault();
- app.formExit();
- } );
- // After form save.
- $builder.on( 'wpformsSaved', function( e, data ) {
- /**
- * Remove `newform` parameter, if it's in URL, otherwise we can to get a "race condition".
- * E.g. form settings will be updated before some provider connection is loaded.
- */
- wpf.removeQueryParam( 'newform' );
- } );
- },
- /**
- * Save form.
- *
- * @since 1.0.0
- */
- formSave: function(redirect) {
- var $saveBtn = $( '#wpforms-save' ),
- $icon = $saveBtn.find( 'i.fa-check' ),
- $spinner = $saveBtn.find( 'i.wpforms-loading-spinner' ),
- $label = $saveBtn.find( 'span' ),
- text = $label.text();
- if ( typeof tinyMCE !== 'undefined' ) {
- tinyMCE.triggerSave();
- }
- $label.text( wpforms_builder.saving );
- $icon.addClass( 'wpforms-hidden' );
- $spinner.removeClass( 'wpforms-hidden' );
- var data = {
- action: 'wpforms_save_form',
- data : JSON.stringify($('#wpforms-builder-form').serializeArray()),
- id : s.formID,
- nonce : wpforms_builder.nonce
- };
- return $.post( wpforms_builder.ajax_url, data, function( response ) {
- if ( response.success ) {
- wpf.savedState = wpf.getFormState( '#wpforms-builder-form' );
- wpf.initialSave = false;
- $builder.trigger( 'wpformsSaved', response.data );
- if ( true === redirect && app.isBuilderInPopup() ) {
- app.builderInPopupClose( 'saved' );
- return;
- }
- if ( true === redirect ) {
- window.location.href = wpforms_builder.exit_url;
- }
- } else {
- wpf.debug( response );
- app.formSaveError( response.data );
- }
- } ).fail( function( xhr, textStatus, e ) {
- wpf.debug( xhr );
- app.formSaveError();
- } ).always( function() {
- $label.text( text );
- $spinner.addClass( 'wpforms-hidden' );
- $icon.removeClass( 'wpforms-hidden' );
- } );
- },
- /**
- * Form save error.
- *
- * @since 1.6.3
- *
- * @param {string} error Error message.
- */
- formSaveError: function( error ) {
- // Default error message.
- if ( wpf.empty( error ) ) {
- error = wpforms_builder.error_save_form;
- }
- // Display error in modal window.
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: '<p>' + error + '</p><p>' + wpforms_builder.error_contact_support + '</p>',
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- },
- /**
- * Exit form builder.
- *
- * @since 1.0.0
- */
- formExit: function() {
- if ( app.isBuilderInPopup() && app.formIsSaved() ) {
- app.builderInPopupClose( 'saved' );
- return;
- }
- if ( app.formIsSaved() ) {
- window.location.href = wpforms_builder.exit_url;
- } else {
- $.confirm({
- title: false,
- content: wpforms_builder.exit_confirm,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- closeIcon: true,
- buttons: {
- confirm: {
- text: wpforms_builder.save_exit,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- action: function(){
- app.formSave(true);
- }
- },
- cancel: {
- text: wpforms_builder.exit,
- action: function() {
- closeConfirmation = false;
- if ( app.isBuilderInPopup() ) {
- app.builderInPopupClose( 'canceled' );
- return;
- }
- window.location.href = wpforms_builder.exit_url;
- }
- }
- }
- });
- }
- },
- /**
- * Close confirmation setter.
- *
- * @since {VESRSION}
- *
- * @param {boolean} confirm Close confirmation flag value.
- */
- setCloseConfirmation: function( confirm ) {
- closeConfirmation = ! ! confirm;
- },
- /**
- * Check current form state.
- *
- * @since 1.0.0
- */
- formIsSaved: function() {
- if ( wpf.savedState == wpf.getFormState( '#wpforms-builder-form' ) ) {
- return true;
- } else {
- return false;
- }
- },
- /**
- * Check if the builder opened in the popup (iframe).
- *
- * @since 1.6.2
- *
- * @returns {boolean} True if builder opened in the popup.
- */
- isBuilderInPopup: function() {
- return window.self !== window.parent && window.self.frameElement.id === 'wpforms-builder-iframe';
- },
- /**
- * Close popup with the form builder.
- *
- * @since 1.6.2
- *
- * @param {string} action Performed action: saved or canceled.
- */
- builderInPopupClose: function( action ) {
- var $popup = window.parent.jQuery( '#wpforms-builder-elementor-popup' );
- $popup.find( '#wpforms-builder-iframe' ).attr( 'src', 'about:blank' );
- $popup.fadeOut();
- $popup.trigger( 'wpformsBuilderInPopupClose', [ action, s.formID ] );
- },
- //--------------------------------------------------------------------//
- // General / global
- //--------------------------------------------------------------------//
- /**
- * Element bindings for general and global items
- *
- * @since 1.2.0
- */
- bindUIActionsGeneral: function() {
- // Toggle Smart Tags
- $builder.on( 'click', '.toggle-smart-tag-display', app.smartTagToggle );
- $builder.on( 'click', '.smart-tags-list-display a', app.smartTagInsert );
- // Toggle unfoldable group of fields
- $builder.on( 'click', '.wpforms-panel-fields-group.unfoldable .wpforms-panel-fields-group-title', app.toggleUnfoldableGroup );
- // Hide field preview helper box.
- $builder.on( 'click', '.wpforms-field-helper-hide ', app.hideFieldHelper );
- // Field map table, update key source
- $builder.on('input', '.wpforms-field-map-table .key-source', function(){
- var value = $(this).val(),
- $dest = $(this).parent().parent().find('.key-destination'),
- name = $dest.data('name');
- if (value) {
- $dest.attr('name', name.replace('{source}', value.replace(/[^0-9a-zA-Z_-]/gi, '')));
- }
- });
- // Field map table, delete row
- $builder.on('click', '.wpforms-field-map-table .remove', function(e) {
- e.preventDefault();
- app.fieldMapTableDeleteRow(e, $(this));
- });
- // Field map table, Add row
- $builder.on('click', '.wpforms-field-map-table .add', function(e) {
- e.preventDefault();
- app.fieldMapTableAddRow(e, $(this));
- });
- // Global select field mapping
- $(document).on('wpformsFieldUpdate', app.fieldMapSelect);
- // Restrict user money input fields
- $builder.on( 'input', '.wpforms-money-input', function( event ) {
- var $this = $( this ),
- amount = $this.val(),
- start = $this[ 0 ].selectionStart,
- end = $this[ 0 ].selectionEnd;
- $this.val( amount.replace( /[^0-9.,]/g, '' ) );
- $this[ 0 ].setSelectionRange( start, end );
- } );
- // Format user money input fields
- $builder.on( 'focusout', '.wpforms-money-input', function( event ) {
- var $this = $( this ),
- amount = $this.val();
- if ( ! amount ) {
- return amount;
- }
- var sanitized = wpf.amountSanitize( amount ),
- formatted = wpf.amountFormat( sanitized );
- $this.val( formatted );
- } );
- // Show/hide a group of options.
- $builder.on( 'change', '.wpforms-panel-field-toggle', function() {
- var $input = $( this );
- if ( $input.prop( 'disabled' ) ) {
- return;
- }
- $input.prop( 'disabled', true );
- app.toggleOptionsGroup( $input );
- } );
- // Don't allow users to enable payments if storing entries has
- // been disabled in the General settings.
- $builder.on( 'change', '#wpforms-panel-field-stripe-enable, #wpforms-panel-field-paypal_standard-enable, #wpforms-panel-field-authorize_net-enable, #wpforms-panel-field-square-enable', function( event ) {
- var $this = $( this ),
- gateway = $this.attr( 'id' ).replace( 'wpforms-panel-field-', '' ).replace( '-enable', '' ),
- $notificationWrap = $( '.wpforms-panel-content-section-notifications [id*="-' + gateway + '-wrap"]' );
- if ( $this.prop( 'checked' ) ) {
- var disabled = $( '#wpforms-panel-field-settings-disable_entries' ).prop( 'checked' );
- if ( disabled ) {
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.payments_entries_off,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- $this.prop( 'checked', false );
- } else {
- $notificationWrap.removeClass( 'wpforms-hidden' );
- }
- } else {
- $notificationWrap.addClass( 'wpforms-hidden' );
- $notificationWrap.find( 'input[id*="-' + gateway + '"]' ).prop( 'checked', false );
- }
- } );
- // Don't allow users to disable entries if payments has been enabled.
- $builder.on( 'change', '#wpforms-panel-field-settings-disable_entries', function( event ) {
- var $this = $( this );
- if ( $this.prop( 'checked' ) ) {
- var paymentsEnabled = $( '#wpforms-panel-field-stripe-enable' ).prop( 'checked' ) || $( '#wpforms-panel-field-paypal_standard-enable' ).prop( 'checked' ) || $( '#wpforms-panel-field-authorize_net-enable' ).prop( 'checked' ) || $( '#wpforms-panel-field-square-enable' ).prop( 'checked' );
- if ( paymentsEnabled ) {
- $.confirm( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.payments_on_entries_off,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- $this.prop( 'checked', false );
- } else {
- $.alert( {
- title: wpforms_builder.heads_up,
- content: wpforms_builder.disable_entries,
- icon: 'fa fa-exclamation-circle',
- type: 'orange',
- buttons: {
- confirm: {
- text: wpforms_builder.ok,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- } );
- }
- }
- } );
- // Upload or add an image.
- $builder.on( 'click', '.wpforms-image-upload-add', function( event ) {
- event.preventDefault();
- var $this = $( this ),
- $container = $this.parent(),
- mediaModal;
- mediaModal = wp.media.frames.wpforms_media_frame = wp.media( {
- className: 'media-frame wpforms-media-frame',
- frame: 'select',
- multiple: false,
- title: wpforms_builder.upload_image_title,
- library: {
- type: 'image',
- },
- button: {
- text: wpforms_builder.upload_image_button,
- },
- } );
- mediaModal.on( 'select', function() {
- var mediaAttachment = mediaModal.state().get( 'selection' ).first().toJSON();
- $container.find( '.source' ).val( mediaAttachment.url );
- $container.find( '.preview' ).empty();
- $container.find( '.preview' ).prepend( '<img src="' + mediaAttachment.url + '"><a href="#" title="' + wpforms_builder.upload_image_remove + '" class="wpforms-image-upload-remove"><i class="fa fa-trash-o"></i></a>' );
- if ( $this.data( 'after-upload' ) === 'hide' ) {
- $this.hide();
- }
- $builder.trigger( 'wpformsImageUploadAdd', [ $this, $container ] );
- } );
- // Now that everything has been set, let's open up the frame.
- mediaModal.open();
- } );
- // Remove and uploaded image.
- $builder.on( 'click', '.wpforms-image-upload-remove', function( event ) {
- event.preventDefault();
- var $container = $( this ).parent().parent();
- $container.find( '.preview' ).empty();
- $container.find( '.wpforms-image-upload-add' ).show();
- $container.find( '.source' ).val( '' );
- $builder.trigger( 'wpformsImageUploadRemove', [ $( this ), $container ] );
- });
- // Validate email smart tags in Notifications fields.
- $builder.on( 'blur', '.wpforms-notification .wpforms-panel-field-text input', function() {
- app.validateEmailSmartTags( $( this ) );
- });
- $builder.on( 'blur', '.wpforms-notification .wpforms-panel-field-textarea textarea', function() {
- app.validateEmailSmartTags( $( this ) );
- });
- // Mobile notice button click.
- $builder.on( 'click', '.wpforms-fullscreen-notice-go-back', app.exitBack );
- // License Alert close button click.
- $( '#wpforms-builder-license-alert .close' ).on( 'click', app.exitBack );
- },
- /**
- * Toggle a options group.
- *
- * @since 1.6.3
- *
- * @param {object} $input Toggled field.
- */
- toggleOptionsGroup: function( $input ) {
- var name = $input.attr( 'name' ),
- type = $input.attr( 'type' ),
- value = '',
- $body = $( '.wpforms-panel-field-toggle-body[data-toggle="' + name + '"]' ),
- enableInput = function() {
- $input.prop( 'disabled', false );
- };
- if ( $body.length === 0 ) {
- enableInput();
- return;
- }
- if ( 'checkbox' === type || 'radio' === type ) {
- value = $input.prop( 'checked' ) ? $input.val() : '0';
- } else {
- value = $input.val();
- }
- $body.each( function() {
- var $this = $( this );
- $this.attr( 'data-toggle-value' ).toString() === value.toString() ?
- $this.slideDown( '', enableInput ) :
- $this.slideUp( '', enableInput );
- } );
- },
- /**
- * Toggle all option groups.
- *
- * @since 1.6.3
- *
- * @param {jQuery} $context Context container jQuery object.
- */
- toggleAllOptionGroups: function( $context ) {
- $context = $context || $builder || $( '#wpforms-builder' ) || $( 'body' );
- if ( ! $context ) {
- return;
- }
- // Show a toggled bodies.
- $context.find( '.wpforms-panel-field-toggle' ).each( function() {
- var $input = $( this );
- $input.prop( 'disabled', true );
- app.toggleOptionsGroup( $input );
- } );
- },
- /**
- * Toggle unfoldable group of fields.
- *
- * @since 1.6.8
- *
- * @param {object} e Event object.
- */
- toggleUnfoldableGroup: function( e ) {
- e.preventDefault();
- var $title = $( e.target ),
- $group = $title.closest( '.wpforms-panel-fields-group' ),
- $inner = $group.find( '.wpforms-panel-fields-group-inner' ),
- cookieName = 'wpforms_fields_group_' + $group.data( 'group' );
- if ( $group.hasClass( 'opened' ) ) {
- wpCookies.remove( cookieName );
- $group.removeClass( 'opened' );
- $inner.stop().slideUp();
- } else {
- wpCookies.set( cookieName, 'true', 2592000 ); // 1 month.
- $group.addClass( 'opened' );
- $inner.stop().slideDown();
- }
- },
- /**
- * Hide field preview helper box.
- *
- * @since 1.7.1
- *
- * @param {object} e Event object.
- */
- hideFieldHelper: function( e ) {
- e.preventDefault();
- e.stopPropagation();
- var $helpers = $( '.wpforms-field-helper' ),
- cookieName = 'wpforms_field_helper_hide';
- wpCookies.set( cookieName, 'true', 30 * 24 * 60 * 60 ); // 1 month.
- $helpers.hide();
- },
- /**
- * Smart Tag toggling.
- *
- * @since 1.0.1
- * @since 1.6.9 Simplify method.
- *
- * @param {Event} e Event.
- */
- smartTagToggle: function( e ) {
- e.preventDefault();
- var $this = $( this ),
- $wrapper = $this.closest( '.wpforms-panel-field,.wpforms-field-option-row' );
- if ( $wrapper.hasClass( 'smart-tags-toggling' ) ) {
- return;
- }
- $wrapper.addClass( 'smart-tags-toggling' );
- if ( $this.hasClass( 'smart-tag-showing' ) ) {
- app.removeSmartTagsList( $this );
- return;
- }
- app.insertSmartTagsList( $this );
- },
- /**
- * Remove Smart Tag list.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- */
- removeSmartTagsList: function( $el ) {
- var $wrapper = $el.closest( '.wpforms-panel-field,.wpforms-field-option-row' ),
- $list = $wrapper.find( '.smart-tags-list-display' );
- $el.find( 'span' ).text( wpforms_builder.smart_tags_show );
- $list.slideUp( '', function() {
- $list.remove();
- $el.removeClass( 'smart-tag-showing' );
- $wrapper.removeClass( 'smart-tags-toggling' );
- } );
- },
- /**
- * Insert Smart Tag list.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- */
- insertSmartTagsList: function( $el ) {
- var $wrapper = $el.closest( '.wpforms-panel-field,.wpforms-field-option-row' ),
- $label = $el.closest( 'label' ),
- insideLabel = true,
- smartTagList;
- if ( ! $label.length ) {
- $label = $wrapper.find( 'label' );
- insideLabel = false;
- }
- smartTagList = app.getSmartTagsList( $el, $label.attr( 'for' ).indexOf( 'wpforms-field-option-' ) !== -1 );
- insideLabel ?
- $label.after( smartTagList ) :
- $el.after( smartTagList );
- $el.find( 'span' ).text( wpforms_builder.smart_tags_hide );
- $wrapper.find( '.smart-tags-list-display' ).slideDown( '', function() {
- $el.addClass( 'smart-tag-showing' );
- $wrapper.removeClass( 'smart-tags-toggling' );
- } );
- },
- /**
- * Get Smart Tag list markup.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- * @param {boolean} isFieldOption Is a field option.
- *
- * @returns {string} Smart Tags list markup.
- */
- getSmartTagsList: function( $el, isFieldOption ) {
- var smartTagList;
- smartTagList = '<ul class="smart-tags-list-display unfoldable-cont">';
- smartTagList += app.getSmartTagsListFieldsElements( $el );
- smartTagList += app.getSmartTagsListOtherElements( $el, isFieldOption );
- smartTagList += '</ul>';
- return smartTagList;
- },
- /**
- * Get Smart Tag fields elements markup.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- *
- * @returns {string} Smart Tags list elements markup.
- */
- getSmartTagsListFieldsElements: function( $el ) {
- var type = $el.data( 'type' ),
- fields = app.getSmartTagsFields( $el ),
- smartTagListElements = '';
- if ( ! [ 'fields', 'all' ].includes( type ) ) {
- return '';
- }
- if ( ! fields ) {
- return '<li class="heading">' + wpforms_builder.fields_unavailable + '</li>';
- }
- smartTagListElements += '<li class="heading">' + wpforms_builder.fields_available + '</li>';
- for ( var fieldKey in wpf.orders.fields ) {
- var fieldId = wpf.orders.fields[ fieldKey ];
- if ( ! fields[ fieldId ] ) {
- continue;
- }
- smartTagListElements += app.getSmartTagsListFieldsElement( fields[ fieldId ] );
- }
- return smartTagListElements;
- },
- /**
- * Get fields that possible to create smart tag.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- *
- * @returns {Array} Fields for smart tags.
- */
- getSmartTagsFields: function( $el ) {
- var allowed = $el.data( 'fields' );
- return allowed && allowed.length ? wpf.getFields( allowed.split( ',' ), true ) : wpf.getFields( false, true );
- },
- /**
- * Get field markup for the Smart Tags list.
- *
- * @since 1.6.9
- *
- * @param {object} field A field.
- *
- * @returns {string} Smart Tags field markup.
- */
- getSmartTagsListFieldsElement: function( field ) {
- var label = field.label ?
- wpf.encodeHTMLEntities( wpf.sanitizeHTML( field.label ) ) :
- wpforms_builder.field + ' #' + field.id;
- return '<li><a href="#" data-type="field" data-meta=\'' + field.id + '\'>' + label + '</a></li>';
- },
- /**
- * Get Smart Tag other elements markup.
- *
- * @since 1.6.9
- *
- * @param {jQuery} $el Toggle element.
- * @param {boolean} isFieldOption Is a field option.
- *
- * @returns {string} Smart Tags list elements markup.
- */
- getSmartTagsListOtherElements: function( $el, isFieldOption ) {
- var type = $el.data( 'type' ),
- smartTagListElements;
- if ( type !== 'other' && type !== 'all' ) {
- return '';
- }
- smartTagListElements = '<li class="heading">' + wpforms_builder.other + '</li>';
- for ( var smartTagKey in wpforms_builder.smart_tags ) {
- if ( isFieldOption && wpforms_builder.smart_tags_disabled_for_fields.indexOf( smartTagKey ) > -1 ) {
- continue;
- }
- smartTagListElements += '<li><a href="#" data-type="other" data-meta=\'' + smartTagKey + '\'>' + wpforms_builder.smart_tags[ smartTagKey ] + '</a></li>';
- }
- return smartTagListElements;
- },
- /**
- * Smart Tag insert.
- *
- * @since 1.0.1
- * @since 1.6.9 TinyMCE compatibility.
- *
- * @param {Event} e Event.
- */
- smartTagInsert: function( e ) {
- e.preventDefault();
- var $this = $( this ),
- $list = $this.closest( '.smart-tags-list-display' ),
- $wrapper = $list.closest( '.wpforms-panel-field,.wpforms-field-option-row' ),
- $toggle = $wrapper.find( '.toggle-smart-tag-display' ),
- $input = $wrapper.find( 'input[type=text], textarea' ),
- meta = $this.data( 'meta' ),
- type = $this.data( 'type' ),
- smartTag = type === 'field' ? '{field_id="' + meta + '"}' : '{' + meta + '}',
- editor;
- if ( typeof tinyMCE !== 'undefined' ) {
- editor = tinyMCE.get( $input.prop( 'id' ) );
- if ( editor && ! editor.hasFocus() ) {
- editor.focus( true );
- }
- }
- editor && ! editor.isHidden() ?
- editor.insertContent( smartTag ) :
- $input.insertAtCaret( smartTag );
- // remove list, all done!
- $list.slideUp( '', function() {
- $list.remove();
- } );
- $toggle.find( 'span' ).text( wpforms_builder.smart_tags_show );
- $wrapper.find( '.toggle-smart-tag-display' ).removeClass( 'smart-tag-showing' );
- },
- /**
- * Field map table - Delete row.
- *
- * @since 1.2.0
- * @since 1.6.1.2 Registered `wpformsFieldMapTableDeletedRow` trigger.
- */
- fieldMapTableDeleteRow: function( e, el ) {
- var $this = $( el ),
- $row = $this.closest( 'tr' ),
- $table = $this.closest( 'table' ),
- $block = $row.closest( '.wpforms-builder-settings-block' ),
- total = $table.find( 'tr' ).length;
- if ( total > '1' ) {
- $row.remove();
- $builder.trigger( 'wpformsFieldMapTableDeletedRow', [ $block ] );
- }
- },
- /**
- * Field map table - Add row.
- *
- * @since 1.2.0
- * @since 1.6.1.2 Registered `wpformsFieldMapTableAddedRow` trigger.
- */
- fieldMapTableAddRow: function( e, el ) {
- var $this = $( el ),
- $row = $this.closest( 'tr' ),
- $block = $row.closest( '.wpforms-builder-settings-block' ),
- choice = $row.clone().insertAfter( $row );
- choice.find( 'input' ).val( '' );
- choice.find( 'select :selected' ).prop( 'selected', false );
- choice.find( '.key-destination' ).attr( 'name', '' );
- $builder.trigger( 'wpformsFieldMapTableAddedRow', [ $block, choice ] );
- },
- /**
- * Update field mapped select items on form updates.
- *
- * @since 1.2.0
- * @since 1.6.1.2 Registered `wpformsFieldSelectMapped` trigger.
- */
- fieldMapSelect: function( e, fields ) {
- $( '.wpforms-field-map-select' ).each( function( index, el ) {
- var $this = $( this ),
- selected = $this.find( 'option:selected' ).val(),
- allowedFields = $this.data( 'field-map-allowed' ),
- placeholder = $this.data( 'field-map-placeholder' );
- // Check if custom placeholder was provided.
- if ( typeof placeholder === 'undefined' || ! placeholder ) {
- placeholder = wpforms_builder.select_field;
- }
- // Reset select and add a placeholder option.
- $this.empty().append( $( '<option>', { value: '', text : placeholder } ) );
- // If allowed fields are not defined, bail.
- if ( typeof allowedFields !== 'undefined' && allowedFields ) {
- allowedFields = allowedFields.split( ' ' );
- } else {
- return;
- }
- // Loop through the current fields, if we have fields for the form.
- if ( fields && ! $.isEmptyObject( fields ) ) {
- for ( var key in wpf.orders.fields ) {
- if ( ! Object.prototype.hasOwnProperty.call( wpf.orders.fields, key ) ) {
- continue;
- }
- var fieldID = wpf.orders.fields[ key ],
- label = '';
- if ( ! fields[ fieldID ] ) {
- continue;
- }
- // Prepare the label.
- if ( typeof fields[ fieldID ].label !== 'undefined' && fields[ fieldID ].label.toString().trim() !== '' ) {
- label = wpf.sanitizeHTML( fields[ fieldID ].label.toString().trim() );
- } else {
- label = wpforms_builder.field + ' #' + fieldID;
- }
- // Add to select if it is a field type allowed.
- if ( $.inArray( fields[ fieldID ].type, allowedFields ) >= 0 || $.inArray( 'all-fields', allowedFields ) >= 0 ) {
- $this.append( $( '<option>', { value: fields[ fieldID ].id, text : label } ) );
- }
- }
- }
- // Restore previous value if found.
- if ( selected ) {
- $this.find( 'option[value="' + selected + '"]' ).prop( 'selected', true );
- }
- // Add a "Custom Value" option, if it support.
- var customValueSupport = $this.data( 'custom-value-support' );
- if ( typeof customValueSupport === 'boolean' && customValueSupport ) {
- $this.append(
- $( '<option>', {
- value: 'custom_value',
- text: wpforms_builder.add_custom_value_label,
- class: 'wpforms-field-map-option-custom-value',
- } )
- );
- }
- $builder.trigger( 'wpformsFieldSelectMapped', [ $this ] );
- } );
- },
- /**
- * Validate email smart tags in Notifications fields.
- *
- * @param {object} $el Input field to check the value for.
- *
- * @since 1.4.9
- */
- validateEmailSmartTags: function( $el ) {
- var val = $el.val();
- if ( ! val ) {
- return;
- }
- // Turns '{email@domain.com}' into 'email@domain.com'.
- // Email RegEx inspired by http://emailregex.com
- val = val.replace( /{(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))}/g, function( x ) {
- return x.slice( 1, -1 );
- } );
- $el.val( val );
- },
- //--------------------------------------------------------------------//
- // Alerts (notices).
- //--------------------------------------------------------------------//
- /**
- * Click on the Dismiss notice button.
- *
- * @since 1.6.7
- */
- dismissNotice: function() {
- $builder.on( 'click', '.wpforms-alert-dismissible .wpforms-dismiss-button', function( e ) {
- e.preventDefault();
- var $button = $( this ),
- $alert = $button.closest( '.wpforms-alert' ),
- fieldId = $button.data( 'field-id' );
- $alert.addClass( 'out' );
- setTimeout( function() {
- $alert.remove();
- }, 250 );
- if ( fieldId ) {
- $( '#wpforms-field-option-' + fieldId ).remove();
- }
- } );
- },
- //--------------------------------------------------------------------//
- // Other functions.
- //--------------------------------------------------------------------//
- /**
- * Trim long form titles.
- *
- * @since 1.0.0
- */
- trimFormTitle: function() {
- var $title = $( '.wpforms-center-form-name' );
- if ( $title.text().length > 38 ) {
- var shortTitle = $.trim( $title.text() ).substring( 0, 38 ).split( ' ' ).slice( 0, -1 ).join( ' ' ) + '...';
- $title.text( shortTitle );
- }
- },
- /**
- * Load or refresh color picker.
- *
- * @since 1.2.1
- */
- loadColorPickers: function() {
- $('.wpforms-color-picker').minicolors();
- },
- /**
- * Hotkeys:
- * Ctrl+H - Help.
- * Ctrl+P - Preview.
- * Ctrl+B - Embed.
- * Ctrl+E - Entries.
- * Ctrl+S - Save.
- * Ctrl+Q - Exit.
- * Ctrl+/ - Keyboard Shortcuts modal.
- *
- * @since 1.2.4
- */
- builderHotkeys: function() {
- $( document ).keydown( function( e ) {
- if ( ! e.ctrlKey ) {
- return;
- }
- switch ( e.keyCode ) {
- case 72: // Open Help screen on Ctrl+H.
- $( '#wpforms-help', $builder ).click();
- break;
- case 80: // Open Form Preview tab on Ctrl+P.
- window.open( wpforms_builder.preview_url );
- break;
- case 66: // Trigger the Embed modal on Ctrl+B.
- $( '#wpforms-embed', $builder ).click();
- break;
- case 69: // Open Entries tab on Ctrl+E.
- window.open( wpforms_builder.entries_url );
- break;
- case 83: // Trigger the Builder save on Ctrl+S.
- $( '#wpforms-save', $builder ).click();
- break;
- case 81: // Trigger the Exit on Ctrl+Q.
- $( '#wpforms-exit', $builder ).click();
- break;
- case 191: // Keyboard shortcuts modal on Ctrl+/.
- app.openKeyboardShortcutsModal();
- break;
- default:
- return;
- }
- return false;
- } );
- },
- /**
- * Open Keyboard Shortcuts modal.
- *
- * @since 1.6.9
- */
- openKeyboardShortcutsModal: function() {
- // Close already opened instance.
- if ( $( '.wpforms-builder-keyboard-shortcuts' ).length ) {
- jconfirm.instances[ jconfirm.instances.length - 1 ].close();
- return;
- }
- $.alert( {
- title: wpforms_builder.shortcuts_modal_title,
- content: wpforms_builder.shortcuts_modal_msg + wp.template( 'wpforms-builder-keyboard-shortcuts' )(),
- icon: 'fa fa-keyboard-o',
- type: 'blue',
- boxWidth: '550px',
- smoothContent: false,
- buttons: {
- confirm: {
- text: wpforms_builder.close,
- btnClass: 'btn-confirm',
- keys: [ 'enter' ],
- },
- },
- onOpenBefore: function() {
- this.$body.addClass( 'wpforms-builder-keyboard-shortcuts' );
- },
- } );
- },
- /**
- * Register JS templates for various elements.
- *
- * @since 1.4.8
- */
- registerTemplates: function () {
- if (typeof WPForms === 'undefined') {
- return;
- }
- WPForms.Admin.Builder.Templates.add([
- 'wpforms-builder-confirmations-message-field',
- 'wpforms-builder-conditional-logic-toggle-field'
- ]);
- },
- /**
- * Exit builder.
- *
- * @since 1.5.7
- */
- exitBack: function() {
- if ( 1 < window.history.length && document.referrer ) {
- window.history.back();
- } else {
- window.location.href = wpforms_builder.exit_url;
- }
- },
- };
- // Provide access to public functions/properties.
- return app;
- }( document, window, jQuery ) );
- WPFormsBuilder.init();
|