Нема описа

admin.js 59KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213
  1. /* global wpforms_admin, jconfirm, wpCookies, Choices, List */
  2. ;(function($) {
  3. 'use strict';
  4. // Global settings access.
  5. var s;
  6. // Admin object.
  7. var WPFormsAdmin = {
  8. // Settings.
  9. settings: {
  10. iconActivate: '<i class="fa fa-toggle-on fa-flip-horizontal" aria-hidden="true"></i>',
  11. iconDeactivate: '<i class="fa fa-toggle-on" aria-hidden="true"></i>',
  12. iconInstall: '<i class="fa fa-cloud-download" aria-hidden="true"></i>',
  13. iconSpinner: '<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>',
  14. mediaFrame: false
  15. },
  16. /**
  17. * Start the engine.
  18. *
  19. * @since 1.3.9
  20. */
  21. init: function() {
  22. // Settings shortcut.
  23. s = this.settings;
  24. // Document ready.
  25. $( WPFormsAdmin.ready );
  26. // Forms Overview.
  27. WPFormsAdmin.initFormOverview();
  28. // Entries Single (Details).
  29. WPFormsAdmin.initEntriesSingle();
  30. // Entries List.
  31. WPFormsAdmin.initEntriesList();
  32. // Welcome activation.
  33. WPFormsAdmin.initWelcome();
  34. // Addons List.
  35. $( document ).on( 'wpformsReady', WPFormsAdmin.initAddons );
  36. // Settings.
  37. WPFormsAdmin.initSettings();
  38. // Tools.
  39. WPFormsAdmin.initTools();
  40. // Upgrades (Tools view).
  41. WPFormsAdmin.initUpgrades();
  42. },
  43. /**
  44. * Document ready.
  45. *
  46. * @since 1.3.9
  47. */
  48. ready: function() {
  49. // To prevent jumping (since WP core moves the notices with js),
  50. // they are hidden initially with CSS, then revealed below with JS,
  51. // which runs after they have been moved.
  52. $( '.notice' ).show();
  53. // If there are screen options we have to move them.
  54. $( '#screen-meta-links, #screen-meta' ).prependTo( '#wpforms-header-temp' ).show();
  55. // Init fancy selects via choices.js.
  56. WPFormsAdmin.initChoicesJS();
  57. // Init checkbox multi selects columns.
  58. WPFormsAdmin.initCheckboxMultiselectColumns();
  59. // Init color pickers via minicolors.js.
  60. $( '.wpforms-color-picker' ).minicolors();
  61. // Init fancy File Uploads.
  62. $( '.wpforms-file-upload' ).each( function(){
  63. var $input = $( this ).find( 'input[type=file]' ),
  64. $label = $( this ).find( 'label' ),
  65. labelVal = $label.html();
  66. $input.on( 'change', function( event ) {
  67. var fileName = '';
  68. if ( this.files && this.files.length > 1 ) {
  69. fileName = ( this.getAttribute( 'data-multiple-caption' ) || '' ).replace( '{count}', this.files.length );
  70. } else if( event.target.value ) {
  71. fileName = event.target.value.split( '\\' ).pop();
  72. }
  73. if ( fileName ) {
  74. $label.find( '.fld' ).html( fileName );
  75. } else {
  76. $label.html( labelVal );
  77. }
  78. });
  79. // Firefox bug fix.
  80. $input.on( 'focus', function(){ $input.addClass( 'has-focus' ); }).on( 'blur', function(){ $input.removeClass( 'has-focus' ); });
  81. });
  82. // jquery-confirm defaults.
  83. jconfirm.defaults = {
  84. closeIcon: false,
  85. backgroundDismiss: false,
  86. escapeKey: true,
  87. animationBounce: 1,
  88. useBootstrap: false,
  89. theme: 'modern',
  90. boxWidth: '400px',
  91. animateFromElement: false,
  92. content: wpforms_admin.something_went_wrong,
  93. };
  94. // Upgrade information modal for upgrade links.
  95. $( document ).on( 'click', '.wpforms-upgrade-modal', function() {
  96. $.alert({
  97. title: false,
  98. content: wpforms_admin.upgrade_modal,
  99. icon: 'fa fa-info-circle',
  100. type: 'blue',
  101. boxWidth: '565px',
  102. buttons: {
  103. confirm: {
  104. text: wpforms_admin.ok,
  105. btnClass: 'btn-confirm',
  106. keys: [ 'enter' ],
  107. }
  108. }
  109. });
  110. });
  111. // Lity lightbox.
  112. WPFormsAdmin.initLity();
  113. // Flyout Menu.
  114. WPFormsAdmin.initFlyoutMenu();
  115. // Action available for each binding.
  116. $( document ).trigger( 'wpformsReady' );
  117. },
  118. /**
  119. * Initialize Choices JS elements.
  120. *
  121. * @since 1.4.2
  122. */
  123. initChoicesJS: function() {
  124. $( '.choicesjs-select' ).each( function() {
  125. var $this = $( this ),
  126. args = { searchEnabled: false };
  127. if ( $this.attr( 'multiple' ) ) {
  128. args.searchEnabled = true;
  129. args.removeItemButton = true;
  130. }
  131. if ( $this.data( 'sorting' ) === 'off' ) {
  132. args.shouldSort = false;
  133. }
  134. if ( $this.data( 'search' ) ) {
  135. args.searchEnabled = true;
  136. }
  137. // Translate default strings.
  138. args.loadingText = wpforms_admin.choicesjs_loading;
  139. args.noResultsText = wpforms_admin.choicesjs_no_results;
  140. args.noChoicesText = wpforms_admin.choicesjs_no_choices;
  141. args.itemSelectText = wpforms_admin.choicesjs_item_select;
  142. // Function to run once Choices initialises.
  143. // We need to reproduce a behaviour like on public-facing area for "Edit Entry" page.
  144. args.callbackOnInit = function() {
  145. var self = this,
  146. $element = $( self.passedElement.element ),
  147. $input = $( self.input.element ),
  148. sizeClass = $element.data( 'size-class' );
  149. // Add CSS-class for size.
  150. if ( sizeClass ) {
  151. $( self.containerOuter.element ).addClass( sizeClass );
  152. }
  153. /**
  154. * If a multiple select has selected choices - hide a placeholder input.
  155. * We use a custom styles like a `.screen-reader-text` for it,
  156. * because it avoid an issue with closing a dropdown.
  157. */
  158. if ( $element.prop( 'multiple' ) ) {
  159. // On init event.
  160. if ( self.getValue( true ).length ) {
  161. $input.addClass( self.config.classNames.input + '--hidden' );
  162. }
  163. // On change event.
  164. $element.on( 'change', function() {
  165. self.getValue( true ).length ? $input.addClass( self.config.classNames.input + '--hidden' ) : $input.removeClass( self.config.classNames.input + '--hidden' );
  166. } );
  167. }
  168. };
  169. $this.data( 'choicesjs', new Choices( $this[0], args ) );
  170. } );
  171. },
  172. /**
  173. * Initialize checkbox multi-select columns.
  174. *
  175. * @since 1.4.2
  176. */
  177. initCheckboxMultiselectColumns: function() {
  178. $( document ).on( 'change', '.checkbox-multiselect-columns input', function() {
  179. var $this = $( this ),
  180. $parent = $this.parent(),
  181. $container = $this.closest( '.checkbox-multiselect-columns' ),
  182. label = $parent.text(),
  183. itemID = 'check-item-' + $this.val(),
  184. $item = $container.find( '#' + itemID );
  185. if ( $this.prop( 'checked' ) ) {
  186. $this.parent().addClass( 'checked' );
  187. if ( ! $item.length ) {
  188. $container.find('.second-column ul').append( '<li id="'+itemID+'">'+label+'</li>' );
  189. }
  190. } else {
  191. $this.parent().removeClass( 'checked' );
  192. $container.find( '#' + itemID ).remove();
  193. }
  194. });
  195. $( document ).on( 'click', '.checkbox-multiselect-columns .all', function( event ) {
  196. event.preventDefault();
  197. $( this ).closest( '.checkbox-multiselect-columns' ).find( 'input[type=checkbox]' ).prop( 'checked', true ).trigger( 'change' );
  198. $( this ).remove();
  199. });
  200. },
  201. //--------------------------------------------------------------------//
  202. // Forms Overview
  203. //--------------------------------------------------------------------//
  204. /**
  205. * Element bindings for Form Overview page.
  206. *
  207. * @since 1.3.9
  208. */
  209. initFormOverview: function() {
  210. // Confirm form entry deletion and duplications.
  211. $( document ).on( 'click', '#wpforms-overview .wp-list-table .delete a, #wpforms-overview .wp-list-table .duplicate a', function( event ) {
  212. event.preventDefault();
  213. var url = $( this ).attr( 'href' ),
  214. msg = $( this ).parent().hasClass( 'delete' ) ? wpforms_admin.form_delete_confirm : wpforms_admin.form_duplicate_confirm;
  215. // Trigger alert modal to confirm.
  216. $.confirm({
  217. title: false,
  218. content: msg,
  219. icon: 'fa fa-exclamation-circle',
  220. type: 'orange',
  221. buttons: {
  222. confirm: {
  223. text: wpforms_admin.ok,
  224. btnClass: 'btn-confirm',
  225. keys: [ 'enter' ],
  226. action: function(){
  227. window.location = url;
  228. }
  229. },
  230. cancel: {
  231. text: wpforms_admin.cancel,
  232. keys: [ 'esc' ]
  233. }
  234. }
  235. });
  236. });
  237. },
  238. //--------------------------------------------------------------------//
  239. // Entry Single (Details)
  240. //--------------------------------------------------------------------//
  241. /**
  242. * Element bindings for Entries Single (Details) page.
  243. *
  244. * @since 1.3.9
  245. */
  246. initEntriesSingle: function() {
  247. // Entry navigation hotkeys.
  248. // We only want to listen on the applicable admin page.
  249. if ( 'wpforms-entries' === WPFormsAdmin.getQueryString( 'page' ) && 'details' === WPFormsAdmin.getQueryString( 'view' ) ) {
  250. WPFormsAdmin.entryHotkeys();
  251. }
  252. // Confirm entry deletion.
  253. $( document ).on( 'click', '#wpforms-entries-single .submitdelete', function( event ) {
  254. event.preventDefault();
  255. var url = $( this ).attr( 'href' );
  256. // Trigger alert modal to confirm.
  257. $.confirm({
  258. title: false,
  259. content: wpforms_admin.entry_delete_confirm,
  260. icon: 'fa fa-exclamation-circle',
  261. type: 'orange',
  262. buttons: {
  263. confirm: {
  264. text: wpforms_admin.ok,
  265. btnClass: 'btn-confirm',
  266. keys: [ 'enter' ],
  267. action: function(){
  268. window.location = url;
  269. }
  270. },
  271. cancel: {
  272. text: wpforms_admin.cancel,
  273. keys: [ 'esc' ]
  274. }
  275. }
  276. });
  277. });
  278. // Open Print preview in new window.
  279. $( document ).on( 'click', '#wpforms-entries-single .wpforms-entry-print a', function( event ) {
  280. event.preventDefault();
  281. window.open( $( this ).attr( 'href' ) );
  282. });
  283. // Toggle displaying empty fields.
  284. $( document ).on( 'click', '#wpforms-entries-single .wpforms-empty-field-toggle', function( event ) {
  285. event.preventDefault();
  286. // Handle cookie.
  287. if ( wpCookies.get( 'wpforms_entry_hide_empty' ) === 'true' ) {
  288. // User was hiding empty fields, so now display them.
  289. wpCookies.remove( 'wpforms_entry_hide_empty' );
  290. $( this ).text( wpforms_admin.entry_empty_fields_hide );
  291. } else {
  292. // User was seeing empty fields, so now hide them.
  293. wpCookies.set( 'wpforms_entry_hide_empty', 'true', 2592000 ); // 1month.
  294. $( this ).text( wpforms_admin.entry_empty_fields_show );
  295. }
  296. $( '.wpforms-entry-field.empty, .wpforms-edit-entry-field.empty' ).toggle();
  297. });
  298. // Display notes editor.
  299. $( document ).on( 'click', '#wpforms-entries-single .wpforms-entry-notes-new .add', function( event ) {
  300. event.preventDefault();
  301. $( this ).hide().next( 'form' ).stop().slideToggle();
  302. });
  303. // Cancel note.
  304. $( document ).on( 'click', '#wpforms-entries-single .wpforms-entry-notes-new .cancel', function( event ) {
  305. event.preventDefault();
  306. $( this ).closest( 'form' ).stop().slideToggle();
  307. $('.wpforms-entry-notes-new .add').show();
  308. });
  309. // Delete note.
  310. $( document ).on( 'click', '#wpforms-entries-single .wpforms-entry-notes-byline .note-delete', function( event ) {
  311. event.preventDefault();
  312. var url = $( this ).attr( 'href' );
  313. // Trigger alert modal to confirm.
  314. $.confirm({
  315. title: false,
  316. content: wpforms_admin.entry_note_delete_confirm,
  317. icon: 'fa fa-exclamation-circle',
  318. type: 'orange',
  319. buttons: {
  320. confirm: {
  321. text: wpforms_admin.ok,
  322. btnClass: 'btn-confirm',
  323. keys: [ 'enter' ],
  324. action: function(){
  325. window.location = url;
  326. }
  327. },
  328. cancel: {
  329. text: wpforms_admin.cancel,
  330. keys: [ 'esc' ]
  331. }
  332. }
  333. });
  334. });
  335. },
  336. /**
  337. * Hotkeys for Entries Single (Details) page.
  338. *
  339. * j triggers previous entry, k triggers next entry.
  340. *
  341. * @since 1.4.0
  342. */
  343. entryHotkeys: function() {
  344. $( document ).keydown( function( event ) {
  345. if ( 74 === event.keyCode && ! WPFormsAdmin.isFormTypeNode( event.target.nodeName ) ) {
  346. // j key has been pressed outside of a form element, go to
  347. // the previous entry.
  348. var prevEntry = $('#wpforms-entry-prev-link').attr( 'href' );
  349. if ( '#' !== prevEntry ) {
  350. window.location.href = prevEntry;
  351. }
  352. } else if ( 75 === event.keyCode && ! WPFormsAdmin.isFormTypeNode( event.target.nodeName ) ) {
  353. // k key has been pressed outside of a form element, go to
  354. // the previous entry.
  355. var nextEntry = $('#wpforms-entry-next-link').attr( 'href' );
  356. if ( '#' !== nextEntry ) {
  357. window.location.href = nextEntry;
  358. }
  359. }
  360. });
  361. },
  362. //--------------------------------------------------------------------//
  363. // Entry List
  364. //--------------------------------------------------------------------//
  365. /**
  366. * Element bindings for Entries List table page.
  367. *
  368. * @since 1.3.9
  369. */
  370. initEntriesList: function() {
  371. $( document ).on( 'click', '#wpforms-entries-table-edit-columns', function( event ) {
  372. event.preventDefault();
  373. WPFormsAdmin.entriesListFieldColumn();
  374. });
  375. // Toggle form selector dropdown.
  376. $( document ).on( 'click', '#wpforms-entries-list .form-selector .toggle', function( event ) {
  377. event.preventDefault();
  378. $( this ).toggleClass( 'active' ).next( '.form-list' ).toggle();
  379. });
  380. // Confirm bulk entry deletion.
  381. $( document ).on( 'click', '#wpforms-entries-table #doaction', function( event ) {
  382. var $btn = $( this ),
  383. $form = $btn.closest( 'form' ),
  384. $table = $form.find( 'table' ),
  385. $action = $form.find( 'select[name=action]' ),
  386. $checked = $table.find( 'input[name^=entry_id]:checked' );
  387. if ( 'delete' !== $action.val() || ! $checked.length ) {
  388. return;
  389. }
  390. event.preventDefault();
  391. // Trigger alert modal to confirm.
  392. $.confirm( {
  393. title: false,
  394. content: wpforms_admin.entry_delete_n_confirm.replace( '{entry_count}', $checked.length ),
  395. icon: 'fa fa-exclamation-circle',
  396. type: 'orange',
  397. buttons: {
  398. confirm: {
  399. text: wpforms_admin.ok,
  400. btnClass: 'btn-confirm',
  401. keys: [ 'enter' ],
  402. action: function() {
  403. $form.submit();
  404. },
  405. },
  406. cancel: {
  407. text: wpforms_admin.cancel,
  408. keys: [ 'esc' ],
  409. },
  410. },
  411. } );
  412. } );
  413. // Confirm entry deletion.
  414. $( document ).on( 'click', '#wpforms-entries-list .wp-list-table .delete', function( event ) {
  415. event.preventDefault();
  416. var url = $( this ).attr( 'href' );
  417. // Trigger alert modal to confirm.
  418. $.confirm({
  419. title: false,
  420. content: wpforms_admin.entry_delete_confirm,
  421. icon: 'fa fa-exclamation-circle',
  422. type: 'orange',
  423. buttons: {
  424. confirm: {
  425. text: wpforms_admin.ok,
  426. btnClass: 'btn-confirm',
  427. keys: [ 'enter' ],
  428. action: function(){
  429. window.location = url;
  430. }
  431. },
  432. cancel: {
  433. text: wpforms_admin.cancel,
  434. keys: [ 'esc' ]
  435. }
  436. }
  437. });
  438. });
  439. // Toggle entry stars.
  440. $( document ).on( 'click', '#wpforms-entries-list .wp-list-table .indicator-star', function( event ) {
  441. event.preventDefault();
  442. var $this = $( this ),
  443. task = '',
  444. total = Number( $( '#wpforms-entries-list .starred-num' ).text() ),
  445. id = $this.data( 'id' ),
  446. formId = $this.data( 'form-id' );
  447. if ( $this.hasClass( 'star' ) ) {
  448. task = 'star';
  449. total++;
  450. $this.attr( 'title', wpforms_admin.entry_unstar );
  451. } else {
  452. task = 'unstar';
  453. total--;
  454. $this.attr( 'title', wpforms_admin.entry_star );
  455. }
  456. $this.toggleClass( 'star unstar' );
  457. $( '#wpforms-entries-list .starred-num' ).text( total );
  458. var data = {
  459. task : task,
  460. action : 'wpforms_entry_list_star',
  461. nonce : wpforms_admin.nonce,
  462. entryId : id,
  463. formId : formId,
  464. };
  465. $.post( wpforms_admin.ajax_url, data );
  466. });
  467. // Toggle entry read state.
  468. $( document ).on( 'click', '#wpforms-entries-list .wp-list-table .indicator-read', function( event ) {
  469. event.preventDefault();
  470. var $this = $( this ),
  471. task = '',
  472. total = Number( $( '#wpforms-entries-list .unread-num' ).text() ),
  473. id = $this.data( 'id' );
  474. if ( $this.hasClass( 'read' ) ) {
  475. task = 'read';
  476. total--;
  477. $this.attr( 'title', wpforms_admin.entry_unread );
  478. } else {
  479. task = 'unread';
  480. total++;
  481. $this.attr( 'title', wpforms_admin.entry_read );
  482. }
  483. $this.toggleClass( 'read unread' );
  484. $( '#wpforms-entries-list .unread-num' ).text( total );
  485. var data = {
  486. task : task,
  487. action : 'wpforms_entry_list_read',
  488. nonce : wpforms_admin.nonce,
  489. entryId : id,
  490. formId : $this.data( 'form-id' ),
  491. };
  492. $.post( wpforms_admin.ajax_url, data );
  493. });
  494. // Confirm mass entry deletion - this deletes ALL entries.
  495. $( document ).on( 'click', '#wpforms-entries-list .form-details-actions-deleteall', function( event ) {
  496. event.preventDefault();
  497. var url = $( this ).attr( 'href' ),
  498. $table = $( '#wpforms-entries-table' ),
  499. filteredCount = $table.data( 'filtered-count' ) ? parseInt( $table.data( 'filtered-count' ), 10 ) : 0,
  500. data = {
  501. 'action': 'wpforms_entry_list_process_delete_all',
  502. 'form_id': $table.find( 'input[name="form_id"]' ).val(),
  503. 'date': $table.find( 'input[name="date"]' ).val(),
  504. 'search': {
  505. 'field': $table.find( 'select[name="search[field]"]' ).val(),
  506. 'comparison': $table.find( 'select[name="search[comparison]"]' ).val(),
  507. 'term': $table.find( 'input[name="search[term]"]' ).val(),
  508. },
  509. 'nonce': wpforms_admin.nonce,
  510. 'url': url,
  511. };
  512. // Trigger alert modal to confirm.
  513. $.confirm( {
  514. title: wpforms_admin.heads_up,
  515. content: filteredCount && $( '#wpforms-reset-filter' ).length ? wpforms_admin.entry_delete_n_confirm.replace( '{entry_count}', filteredCount ) : wpforms_admin.entry_delete_all_confirm,
  516. icon: 'fa fa-exclamation-circle',
  517. type: 'orange',
  518. buttons: {
  519. confirm: {
  520. text: wpforms_admin.ok,
  521. btnClass: 'btn-confirm',
  522. keys: [ 'enter' ],
  523. action: function() {
  524. $.get( wpforms_admin.ajax_url, data )
  525. .done( function( response ) {
  526. if ( response.success ) {
  527. window.location = ! _.isEmpty( response.data ) ? response.data : url;
  528. return;
  529. }
  530. if ( ! _.isEmpty( response.data ) ) {
  531. console.error( response.data );
  532. }
  533. } );
  534. }
  535. },
  536. cancel: {
  537. text: wpforms_admin.cancel,
  538. keys: [ 'esc' ]
  539. }
  540. }
  541. } );
  542. } );
  543. // Check for new form entries using Heartbeat API.
  544. $( document ).on( 'heartbeat-send', function ( event, data ) {
  545. var $entriesList = $( '#wpforms-entries-list' );
  546. // Works on entry list page only.
  547. if ( ! $entriesList.length || $entriesList.find( '.wpforms-dash-widget' ).length ) {
  548. return;
  549. }
  550. var last_entry_id = $entriesList.find( '#wpforms-entries-table' ).data( 'last-entry-id' );
  551. // When entries list is filtered, there is no data param at all.
  552. if ( typeof last_entry_id === 'undefined' ) {
  553. return;
  554. }
  555. data.wpforms_new_entries_entry_id = last_entry_id;
  556. data.wpforms_new_entries_form_id = $entriesList.find( 'input[name=form_id]' ).val();
  557. } );
  558. // Display entries list notification if Heartbeat API new form entries check is successful.
  559. $( document ).on( 'heartbeat-tick', function ( event, data ) {
  560. var columnCount;
  561. var $entriesList = $( '#wpforms-entries-list' );
  562. // Works on entry list page only.
  563. if ( ! $entriesList.length ) {
  564. return;
  565. }
  566. if ( ! data.wpforms_new_entries_notification ) {
  567. return;
  568. }
  569. columnCount = $entriesList.find( '.wp-list-table thead tr' ).first().children().length;
  570. if ( ! $entriesList.find( '.new-entries-notification' ).length ) {
  571. $entriesList.find( '.wp-list-table thead' )
  572. .append( '<tr class="new-entries-notification"><td colspan="' + columnCount + '"><a href=""></a></td></tr>' );
  573. }
  574. var $link = $entriesList.find( '.new-entries-notification a' );
  575. $link
  576. .text( data.wpforms_new_entries_notification )
  577. .slideDown( {
  578. start: function() {
  579. $link.css( 'display', 'block' );
  580. },
  581. always: function() {
  582. $link.css( 'display', 'block' );
  583. },
  584. } );
  585. } );
  586. },
  587. /**
  588. * Display settings to change the entry list field columns/
  589. *
  590. * @since 1.4.0
  591. */
  592. entriesListFieldColumn: function() {
  593. $.alert({
  594. title: wpforms_admin.entry_field_columns,
  595. boxWidth: '500px',
  596. content: s.iconSpinner + $( '#wpforms-field-column-select' ).html(),
  597. onContentReady: function() {
  598. var $modalContent = this.$content,
  599. $select = $modalContent.find( 'select' ),
  600. choices = new Choices( $select[0], {
  601. shouldSort: false,
  602. removeItemButton: true,
  603. loadingText: wpforms_admin.choicesjs_loading,
  604. noResultsText: wpforms_admin.choicesjs_no_results,
  605. noChoicesText: wpforms_admin.choicesjs_no_choices,
  606. itemSelectText: wpforms_admin.choicesjs_item_select,
  607. callbackOnInit: function() {
  608. $modalContent.find( '.fa' ).remove();
  609. $modalContent.find( 'form' ).show();
  610. }
  611. });
  612. $( '.jconfirm-content-pane, .jconfirm-box' ).css( 'overflow','visible' );
  613. choices.passedElement.element.addEventListener( 'change', function() {
  614. // Without `true` parameter dropdown will be hidden together with modal window when `Enter` is pressed.
  615. choices.hideDropdown( true );
  616. }, false );
  617. },
  618. buttons: {
  619. confirm: {
  620. text: wpforms_admin.save_refresh,
  621. btnClass: 'btn-confirm',
  622. keys: [ 'enter' ],
  623. action: function() {
  624. this.$content.find( 'form' ).submit();
  625. }
  626. },
  627. cancel: {
  628. text: wpforms_admin.cancel,
  629. keys: [ 'esc' ]
  630. }
  631. }
  632. });
  633. },
  634. //--------------------------------------------------------------------//
  635. // Welcome Activation.
  636. //--------------------------------------------------------------------//
  637. /**
  638. * Welcome activation page.
  639. *
  640. * @since 1.3.9
  641. */
  642. initWelcome: function() {
  643. // Open modal and play How To video.
  644. $( document ).on( 'click', '#wpforms-welcome .play-video', function( event ) {
  645. event.preventDefault();
  646. var video = '<div class="video-container"><iframe width="1280" height="720" src="https://www.youtube-nocookie.com/embed/o2nE1P74WxQ?rel=0&amp;showinfo=0&amp;autoplay=1" frameborder="0" allowfullscreen></iframe></div>';
  647. $.dialog({
  648. title: false,
  649. content: video,
  650. closeIcon: true,
  651. boxWidth: '70%'
  652. });
  653. });
  654. },
  655. //--------------------------------------------------------------------//
  656. // Addons List.
  657. //--------------------------------------------------------------------//
  658. /**
  659. * Element bindings for Addons List page.
  660. *
  661. * @since 1.3.9
  662. */
  663. initAddons: function() {
  664. // Only run on the addons page.
  665. if ( ! $( '#wpforms-admin-addons' ).length ) {
  666. return;
  667. }
  668. WPFormsAdmin.matchHeightAddonBlocks();
  669. // Addons searching.
  670. if ( $( '#wpforms-admin-addons-list' ).length ) {
  671. var addonSearch = new List( 'wpforms-admin-addons-list', {
  672. valueNames: [ 'addon-name' ] } );
  673. $( '#wpforms-admin-addons-search' ).on( 'keyup', function() {
  674. var searchTerm = $( this ).val(),
  675. $heading = $( '#addons-heading' );
  676. if ( searchTerm ) {
  677. $heading.text( wpforms_admin.addon_search );
  678. } else {
  679. $heading.text( $heading.data( 'text' ) );
  680. }
  681. addonSearch.search( searchTerm );
  682. } );
  683. }
  684. $( window ).on( 'resize', WPFormsAdmin.matchHeightAddonBlocks );
  685. // Toggle an addon state.
  686. $( document ).on( 'click', '#wpforms-admin-addons .addon-item button', function( event ) {
  687. event.preventDefault();
  688. if ( $( this ).hasClass( 'disabled' ) ) {
  689. return false;
  690. }
  691. WPFormsAdmin.addonToggle( $( this ) );
  692. } );
  693. },
  694. /**
  695. * Change plugin/addon state.
  696. *
  697. * @since 1.6.3
  698. *
  699. * @param {string} plugin Plugin slug or URL for download.
  700. * @param {string} state State status activate|deactivate|install.
  701. * @param {string} pluginType Plugin type addon or plugin.
  702. * @param {Function} callback Callback for get result from AJAX.
  703. */
  704. setAddonState: function( plugin, state, pluginType, callback ) {
  705. var actions = {
  706. 'activate': 'wpforms_activate_addon',
  707. 'install': 'wpforms_install_addon',
  708. 'deactivate': 'wpforms_deactivate_addon',
  709. },
  710. action = actions[ state ];
  711. if ( ! action ) {
  712. return;
  713. }
  714. var data = {
  715. action: action,
  716. nonce: wpforms_admin.nonce,
  717. plugin: plugin,
  718. type: pluginType,
  719. };
  720. $.post( wpforms_admin.ajax_url, data, function( res ) {
  721. callback( res );
  722. } ).fail( function( xhr ) {
  723. console.log( xhr.responseText );
  724. } );
  725. },
  726. /**
  727. * Toggle addon state.
  728. *
  729. * @since 1.3.9
  730. */
  731. addonToggle: function( $btn ) {
  732. var $addon = $btn.closest( '.addon-item' ),
  733. plugin = $btn.attr( 'data-plugin' ),
  734. pluginType = $btn.attr( 'data-type' ),
  735. state,
  736. cssClass,
  737. stateText,
  738. buttonText,
  739. errorText,
  740. successText;
  741. if ( $btn.hasClass( 'status-go-to-url' ) ) {
  742. // Open url in new tab.
  743. window.open( $btn.attr( 'data-plugin' ), '_blank' );
  744. return;
  745. }
  746. $btn.prop( 'disabled', true ).addClass( 'loading' );
  747. $btn.html( s.iconSpinner );
  748. if ( $btn.hasClass( 'status-active' ) ) {
  749. // Deactivate.
  750. state = 'deactivate';
  751. cssClass = 'status-installed';
  752. if ( pluginType === 'plugin' ) {
  753. cssClass += ' button button-secondary';
  754. }
  755. stateText = wpforms_admin.addon_inactive;
  756. buttonText = wpforms_admin.addon_activate;
  757. errorText = wpforms_admin.addon_deactivate;
  758. if ( pluginType === 'addon' ) {
  759. buttonText = s.iconActivate + buttonText;
  760. errorText = s.iconDeactivate + errorText;
  761. }
  762. } else if ( $btn.hasClass( 'status-installed' ) ) {
  763. // Activate.
  764. state = 'activate';
  765. cssClass = 'status-active';
  766. if ( pluginType === 'plugin' ) {
  767. cssClass += ' button button-secondary disabled';
  768. }
  769. stateText = wpforms_admin.addon_active;
  770. buttonText = wpforms_admin.addon_deactivate;
  771. if ( pluginType === 'addon' ) {
  772. buttonText = s.iconDeactivate + buttonText;
  773. errorText = s.iconActivate + wpforms_admin.addon_activate;
  774. } else if ( pluginType === 'plugin' ) {
  775. buttonText = wpforms_admin.addon_activated;
  776. errorText = wpforms_admin.addon_activate;
  777. }
  778. } else if ( $btn.hasClass( 'status-missing' ) ) {
  779. // Install & Activate.
  780. state = 'install';
  781. cssClass = 'status-active';
  782. if ( pluginType === 'plugin' ) {
  783. cssClass += ' button disabled';
  784. }
  785. stateText = wpforms_admin.addon_active;
  786. buttonText = wpforms_admin.addon_activated;
  787. errorText = s.iconInstall;
  788. if ( pluginType === 'addon' ) {
  789. buttonText = s.iconActivate + wpforms_admin.addon_deactivate;
  790. errorText += wpforms_admin.addon_install;
  791. }
  792. } else {
  793. return;
  794. }
  795. // eslint-disable-next-line complexity
  796. WPFormsAdmin.setAddonState( plugin, state, pluginType, function( res ) {
  797. if ( res.success ) {
  798. if ( 'install' === state ) {
  799. $btn.attr( 'data-plugin', res.data.basename );
  800. successText = res.data.msg;
  801. if ( ! res.data.is_activated ) {
  802. stateText = wpforms_admin.addon_inactive;
  803. buttonText = 'plugin' === pluginType ? wpforms_admin.addon_activate : s.iconActivate + wpforms_admin.addon_activate;
  804. cssClass = 'plugin' === pluginType ? 'status-installed button button-secondary' : 'status-installed';
  805. }
  806. } else {
  807. successText = res.data;
  808. }
  809. $addon.find( '.actions' ).append( '<div class="msg success">' + successText + '</div>' );
  810. $addon.find( 'span.status-label' )
  811. .removeClass( 'status-active status-installed status-missing' )
  812. .addClass( cssClass )
  813. .removeClass( 'button button-primary button-secondary disabled' )
  814. .text( stateText );
  815. $btn
  816. .removeClass( 'status-active status-installed status-missing' )
  817. .removeClass( 'button button-primary button-secondary disabled' )
  818. .addClass( cssClass ).html( buttonText );
  819. } else {
  820. if ( 'object' === typeof res.data ) {
  821. if ( pluginType === 'addon' ) {
  822. $addon.find( '.actions' ).append( '<div class="msg error">' + wpforms_admin.addon_error + '</div>' );
  823. } else {
  824. $addon.find( '.actions' ).append( '<div class="msg error">' + wpforms_admin.plugin_error + '</div>' );
  825. }
  826. } else {
  827. $addon.find( '.actions' ).append( '<div class="msg error">' + res.data + '</div>' );
  828. }
  829. if ( 'install' === state && 'plugin' === pluginType ) {
  830. $btn.addClass( 'status-go-to-url' ).removeClass( 'status-missing' );
  831. }
  832. $btn.html( errorText );
  833. }
  834. $btn.prop( 'disabled', false ).removeClass( 'loading' );
  835. // Automatically clear addon messages after 3 seconds.
  836. setTimeout( function() {
  837. $( '.addon-item .msg' ).remove();
  838. }, 3000 );
  839. } );
  840. },
  841. /**
  842. * Display all addon boxes as the same height.
  843. *
  844. * @since 1.6.3
  845. */
  846. matchHeightAddonBlocks: function() {
  847. $( '.addon-item .details' ).matchHeight( { byrow: false, property: 'height' } );
  848. },
  849. //--------------------------------------------------------------------//
  850. // Settings.
  851. //--------------------------------------------------------------------//
  852. /**
  853. * Element bindings for Settings page.
  854. *
  855. * @since 1.3.9
  856. */
  857. initSettings: function() {
  858. // On ready events.
  859. $( document ).on( 'wpformsReady', function() {
  860. // Only proceed if we're on the settings page.
  861. if ( ! $( '#wpforms-settings' ).length ) {
  862. return;
  863. }
  864. // Watch for hashes and scroll to if found.
  865. // Display all addon boxes as the same height.
  866. var integrationFocus = WPFormsAdmin.getQueryString( 'wpforms-integration' ),
  867. jumpTo = WPFormsAdmin.getQueryString( 'jump' );
  868. if ( integrationFocus ) {
  869. $( 'body' ).animate({
  870. scrollTop: $( '#wpforms-integration-'+integrationFocus ).offset().top
  871. }, 1000 );
  872. } else if ( jumpTo ) {
  873. $( 'body' ).animate({
  874. scrollTop: $( '#'+jumpTo ).offset().top
  875. }, 1000 );
  876. }
  877. // Settings conditional logic.
  878. $( '.wpforms-admin-settings-form' ).conditions( [
  879. // Misc > Disable User Cookies visibility.
  880. {
  881. conditions: {
  882. element: '#wpforms-setting-gdpr',
  883. type: 'checked',
  884. operator: 'is'
  885. },
  886. actions: {
  887. if: {
  888. element: '#wpforms-setting-row-gdpr-disable-uuid,#wpforms-setting-row-gdpr-disable-details',
  889. action: 'show'
  890. },
  891. else : {
  892. element: '#wpforms-setting-row-gdpr-disable-uuid,#wpforms-setting-row-gdpr-disable-details',
  893. action: 'hide'
  894. }
  895. },
  896. effect: 'appear'
  897. },
  898. // CAPTCHA > Type.
  899. {
  900. conditions: {
  901. element: 'input[name=captcha-provider]:checked',
  902. type: 'value',
  903. operator: '=',
  904. condition: 'hcaptcha',
  905. },
  906. actions: {
  907. if: [
  908. {
  909. element: '.wpforms-setting-row',
  910. action: 'show',
  911. },
  912. {
  913. element: '.wpforms-setting-recaptcha, #wpforms-setting-row-captcha-provider .desc, #wpforms-setting-row-recaptcha-site-key, #wpforms-setting-row-recaptcha-secret-key, #wpforms-setting-row-recaptcha-fail-msg',
  914. action: 'hide',
  915. },
  916. ],
  917. },
  918. effect: 'appear',
  919. },
  920. {
  921. conditions: {
  922. element: 'input[name=captcha-provider]:checked',
  923. type: 'value',
  924. operator: '=',
  925. condition: 'recaptcha',
  926. },
  927. actions: {
  928. if: [
  929. {
  930. element: '.wpforms-setting-row',
  931. action: 'show',
  932. },
  933. {
  934. element: '#wpforms-setting-row-captcha-provider .desc, #wpforms-setting-row-hcaptcha-heading, #wpforms-setting-row-hcaptcha-site-key, #wpforms-setting-row-hcaptcha-secret-key, #wpforms-setting-row-hcaptcha-fail-msg',
  935. action: 'hide',
  936. },
  937. ],
  938. },
  939. effect: 'appear',
  940. },
  941. {
  942. conditions: {
  943. element: 'input[name=captcha-provider]:checked',
  944. type: 'value',
  945. operator: '=',
  946. condition: 'none',
  947. },
  948. actions: {
  949. if: [
  950. {
  951. element: '.wpforms-setting-row',
  952. action: 'hide',
  953. },
  954. {
  955. element: '.wpforms-setting-captcha-heading, #wpforms-setting-row-captcha-provider, #wpforms-setting-row-captcha-provider .desc',
  956. action: 'show',
  957. },
  958. ],
  959. },
  960. effect: 'appear',
  961. },
  962. ] );
  963. });
  964. // Form styles plugin setting.
  965. $( document ).on( 'change', '#wpforms-setting-disable-css', function() {
  966. WPFormsAdmin.settingsFormStylesAlert( $( this ).val() );
  967. });
  968. // Image upload fields.
  969. $( document ).on( 'click', '.wpforms-setting-row-image button', function( event ) {
  970. event.preventDefault();
  971. WPFormsAdmin.imageUploadModal( $( this ) );
  972. });
  973. // Verify license key.
  974. $( document ).on( 'click', '#wpforms-setting-license-key-verify', function( event ) {
  975. event.preventDefault();
  976. WPFormsAdmin.licenseVerify( $( this ) );
  977. } );
  978. // Show message for license field.
  979. $( document ).on( 'click', '.wpforms-setting-license-wrapper', function( event ) {
  980. event.preventDefault();
  981. var $keyField = $( '#wpforms-setting-license-key' );
  982. if ( ! $keyField.length ) {
  983. return;
  984. }
  985. if ( ! $keyField.prop( 'disabled' ) ) {
  986. return;
  987. }
  988. WPFormsAdmin.licenseEditMessage();
  989. } );
  990. // Deactivate license key.
  991. $( document ).on( 'click', '#wpforms-setting-license-key-deactivate', function( event ) {
  992. event.preventDefault();
  993. WPFormsAdmin.licenseDeactivate( $( this ) );
  994. });
  995. // Refresh license key.
  996. $( document ).on( 'click', '#wpforms-setting-license-key-refresh', function( event ) {
  997. event.preventDefault();
  998. WPFormsAdmin.licenseRefresh( $( this ) );
  999. });
  1000. /**
  1001. * @todo Refactor providers settings tab. Code below is legacy.
  1002. */
  1003. // Integration connect.
  1004. $( document ).on( 'click', '.wpforms-settings-provider-connect', function( event ) {
  1005. event.preventDefault();
  1006. var button = $( this );
  1007. WPFormsAdmin.integrationConnect( button );
  1008. });
  1009. // Integration account disconnect.
  1010. $( document ).on( 'click', '.wpforms-settings-provider-accounts-list a', function( event ) {
  1011. event.preventDefault();
  1012. WPFormsAdmin.integrationDisconnect( $( this ) );
  1013. });
  1014. // Integration individual display toggling.
  1015. $( document ).on( 'click', '.wpforms-settings-provider:not(.focus-out) .wpforms-settings-provider-header', function( event ) {
  1016. event.preventDefault();
  1017. var $this = $( this );
  1018. $this
  1019. .parent()
  1020. .find( '.wpforms-settings-provider-accounts' )
  1021. .stop()
  1022. .slideToggle( '', function() {
  1023. $this.parent().find( '.wpforms-settings-provider-logo i' ).toggleClass( 'fa-chevron-right fa-chevron-down' );
  1024. } );
  1025. } );
  1026. // Integration accounts display toggling.
  1027. $( document ).on( 'click', '.wpforms-settings-provider-accounts-toggle a', function( event ) {
  1028. event.preventDefault();
  1029. var $connectFields = $( this ).parent().next( '.wpforms-settings-provider-accounts-connect' );
  1030. $connectFields.find( 'input[type=text], input[type=password]' ).val('');
  1031. $connectFields.stop().slideToggle();
  1032. });
  1033. // CAPTCHA settings page: type toggling.
  1034. $( document ).on( 'change', '#wpforms-setting-row-captcha-provider input', function() {
  1035. var $preview = $( '#wpforms-setting-row-captcha-preview' );
  1036. if ( 'hcaptcha' === this.value ) {
  1037. $preview.removeClass( 'wpforms-hidden' );
  1038. } else if ( 'none' === this.value ) {
  1039. $preview.addClass( 'wpforms-hidden' );
  1040. } else {
  1041. $( '#wpforms-setting-row-recaptcha-type input:checked' ).trigger( 'change' );
  1042. }
  1043. if ( $preview.find( '.wpforms-captcha-preview' ).length ) {
  1044. $preview.find( '.wpforms-captcha-preview' ).empty();
  1045. $preview.find( '.wpforms-captcha-placeholder' ).removeClass( 'wpforms-hidden' );
  1046. }
  1047. } );
  1048. // CAPTCHA settings page: reCATCHA type toggling.
  1049. $( document ).on( 'change', '#wpforms-setting-row-recaptcha-type input', function() {
  1050. $( '#wpforms-setting-row-captcha-preview' ).toggleClass( 'wpforms-hidden', 'v2' !== this.value );
  1051. $( '#wpforms-setting-row-recaptcha-v3-threshold' ).toggleClass( 'wpforms-hidden', 'v3' !== this.value );
  1052. } );
  1053. },
  1054. /**
  1055. * Alert users if they change form styles to something that may give
  1056. * unexpected results.
  1057. *
  1058. * @since 1.5.0
  1059. */
  1060. settingsFormStylesAlert: function( value ) {
  1061. if ( '2' === value ) {
  1062. var msg = wpforms_admin.settings_form_style_base;
  1063. } else if ( '3' === value ) {
  1064. var msg = wpforms_admin.settings_form_style_none;
  1065. } else {
  1066. return;
  1067. }
  1068. $.alert({
  1069. title: wpforms_admin.heads_up,
  1070. content: msg,
  1071. icon: 'fa fa-exclamation-circle',
  1072. type: 'orange',
  1073. buttons: {
  1074. confirm: {
  1075. text: wpforms_admin.ok,
  1076. btnClass: 'btn-confirm',
  1077. keys: [ 'enter' ],
  1078. }
  1079. }
  1080. });
  1081. },
  1082. /**
  1083. * Image upload modal window.
  1084. *
  1085. * @since 1.3.0
  1086. */
  1087. imageUploadModal: function( el ) {
  1088. if ( s.media_frame ) {
  1089. s.media_frame.open();
  1090. return;
  1091. }
  1092. var $setting = $( el ).closest( '.wpforms-setting-field' );
  1093. s.media_frame = wp.media.frames.wpforms_media_frame = wp.media({
  1094. className: 'media-frame wpforms-media-frame',
  1095. frame: 'select',
  1096. multiple: false,
  1097. title: wpforms_admin.upload_image_title,
  1098. library: {
  1099. type: 'image'
  1100. },
  1101. button: {
  1102. text: wpforms_admin.upload_image_button
  1103. }
  1104. });
  1105. s.media_frame.on( 'select', function(){
  1106. // Grab our attachment selection and construct a JSON representation of the model.
  1107. var media_attachment = s.media_frame.state().get( 'selection' ).first().toJSON();
  1108. // Send the attachment URL to our custom input field via jQuery.
  1109. $setting.find( 'input[type=text]' ).val( media_attachment.url );
  1110. $setting.find( 'img' ).remove();
  1111. $setting.prepend( '<img src="'+media_attachment.url+'">' );
  1112. });
  1113. // Now that everything has been set, let's open up the frame.
  1114. s.media_frame.open();
  1115. },
  1116. /**
  1117. * Verify a license key.
  1118. *
  1119. * @since 1.3.9
  1120. *
  1121. * @param {jQuery} $el Verify button element.
  1122. */
  1123. licenseVerify: function( $el ) {
  1124. var $row = $el.closest( '.wpforms-setting-row' ),
  1125. $keyField = $( '#wpforms-setting-license-key' ),
  1126. buttonWidth = $el.outerWidth(),
  1127. buttonLabel = $el.text(),
  1128. data = {
  1129. action: 'wpforms_verify_license',
  1130. nonce: wpforms_admin.nonce,
  1131. license: $keyField.val(),
  1132. };
  1133. $el.html( s.iconSpinner ).css( 'width', buttonWidth ).prop( 'disabled', true );
  1134. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1135. var icon = 'fa fa-check-circle',
  1136. color = 'green',
  1137. msg;
  1138. if ( res.success ) {
  1139. msg = res.data.msg;
  1140. $row.find( '.type, .desc, #wpforms-setting-license-key-deactivate' ).show();
  1141. $row.find( '.type strong' ).text( res.data.type );
  1142. $( '.wpforms-license-notice' ).remove();
  1143. $keyField.prop( 'disabled', true );
  1144. } else {
  1145. icon = 'fa fa-exclamation-circle';
  1146. color = 'orange';
  1147. msg = res.data;
  1148. $row.find( '.type, .desc, #wpforms-setting-license-key-deactivate' ).hide();
  1149. $keyField.prop( 'disabled', false );
  1150. }
  1151. $.alert( {
  1152. title: false,
  1153. content: msg,
  1154. icon: icon,
  1155. type: color,
  1156. buttons: {
  1157. confirm: {
  1158. text: wpforms_admin.ok,
  1159. btnClass: 'btn-confirm',
  1160. keys: [ 'enter' ],
  1161. },
  1162. },
  1163. } );
  1164. $el.html( buttonLabel ).css( 'width', 'auto' ).prop( 'disabled', false );
  1165. } ).fail( function( xhr ) {
  1166. $keyField.prop( 'disabled', false );
  1167. console.log( xhr.responseText );
  1168. } );
  1169. },
  1170. /**
  1171. * Show message that license key editing is disabled.
  1172. *
  1173. * @since 1.6.5
  1174. */
  1175. licenseEditMessage: function() {
  1176. $.alert( {
  1177. title: wpforms_admin.heads_up,
  1178. content: wpforms_admin.edit_license,
  1179. icon: 'fa fa-exclamation-circle',
  1180. type: 'orange',
  1181. buttons: {
  1182. confirm: {
  1183. text: wpforms_admin.ok,
  1184. btnClass: 'btn-confirm',
  1185. keys: [ 'enter' ],
  1186. },
  1187. },
  1188. } );
  1189. },
  1190. /**
  1191. * Verify a license key.
  1192. *
  1193. * @since 1.3.9
  1194. *
  1195. * @param {Element} el Button element.
  1196. */
  1197. licenseDeactivate: function( el ) {
  1198. var $this = $( el ),
  1199. $row = $this.closest( '.wpforms-setting-row' ),
  1200. buttonWidth = $this.outerWidth(),
  1201. buttonLabel = $this.text(),
  1202. data = {
  1203. action: 'wpforms_deactivate_license',
  1204. nonce: wpforms_admin.nonce,
  1205. };
  1206. $this.html( s.iconSpinner ).css( 'width', buttonWidth ).prop( 'disabled', true );
  1207. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1208. var icon = 'fa fa-info-circle',
  1209. color = 'blue',
  1210. msg = res.data;
  1211. if ( res.success ) {
  1212. $row.find( '#wpforms-setting-license-key' ).val( '' ).prop( 'disabled', false );
  1213. $row.find( '.type, .desc, #wpforms-setting-license-key-deactivate' ).hide();
  1214. } else {
  1215. icon = 'fa fa-exclamation-circle';
  1216. color = 'orange';
  1217. }
  1218. $.alert( {
  1219. title: false,
  1220. content: msg,
  1221. icon: icon,
  1222. type: color,
  1223. buttons: {
  1224. confirm: {
  1225. text: wpforms_admin.ok,
  1226. btnClass: 'btn-confirm',
  1227. keys: [ 'enter' ],
  1228. },
  1229. },
  1230. } );
  1231. $this.html( buttonLabel ).css( 'width', 'auto' ).prop( 'disabled', false );
  1232. } ).fail( function( xhr ) {
  1233. console.log( xhr.responseText );
  1234. } );
  1235. },
  1236. /**
  1237. * Refresh a license key.
  1238. *
  1239. * @since 1.3.9
  1240. */
  1241. licenseRefresh: function( el ) {
  1242. var $this = $( el ),
  1243. $row = $this.closest( '.wpforms-setting-row' ),
  1244. data = {
  1245. action: 'wpforms_refresh_license',
  1246. nonce: wpforms_admin.nonce,
  1247. license: $('#wpforms-setting-license-key').val()
  1248. };
  1249. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1250. var icon = 'fa fa-check-circle',
  1251. color = 'green',
  1252. msg;
  1253. if ( res.success ){
  1254. msg = res.data.msg;
  1255. $row.find( '.type strong' ).text( res.data.type );
  1256. } else {
  1257. icon = 'fa fa-exclamation-circle';
  1258. color = 'orange';
  1259. msg = res.data;
  1260. $row.find( '.type, .desc, #wpforms-setting-license-key-deactivate' ).hide();
  1261. }
  1262. $.alert({
  1263. title: false,
  1264. content: msg,
  1265. icon: icon,
  1266. type: color,
  1267. buttons: {
  1268. confirm: {
  1269. text: wpforms_admin.ok,
  1270. btnClass: 'btn-confirm',
  1271. keys: [ 'enter' ],
  1272. }
  1273. }
  1274. });
  1275. }).fail( function( xhr ) {
  1276. console.log( xhr.responseText );
  1277. });
  1278. },
  1279. /**
  1280. * Connect integration provider account.
  1281. *
  1282. * @param $btn Button (.wpforms-settings-provider-connect) that was clicked to establish connection.
  1283. *
  1284. * @since 1.3.9
  1285. */
  1286. integrationConnect: function( $btn ) {
  1287. var buttonWidth = $btn.outerWidth(),
  1288. buttonLabel = $btn.text(),
  1289. $provider = $btn.closest( '.wpforms-settings-provider' ),
  1290. data = {
  1291. action : 'wpforms_settings_provider_add_' + $btn.data( 'provider' ),
  1292. data : $btn.closest( 'form' ).serialize(),
  1293. provider: $btn.data( 'provider' ),
  1294. nonce : wpforms_admin.nonce,
  1295. },
  1296. errorMessage = wpforms_admin.provider_auth_error;
  1297. $btn.html( 'Connecting...' ).css( 'width', buttonWidth ).prop( 'disabled', true );
  1298. $.post( wpforms_admin.ajax_url, data, function( response ) {
  1299. if ( response.success ) {
  1300. $provider.find( '.wpforms-settings-provider-accounts-list ul' ).append( response.data.html );
  1301. $provider.addClass( 'connected' );
  1302. $btn.closest( '.wpforms-settings-provider-accounts-connect' ).stop().slideToggle();
  1303. } else {
  1304. if (
  1305. Object.prototype.hasOwnProperty.call( response, 'data' ) &&
  1306. Object.prototype.hasOwnProperty.call( response.data, 'error_msg' )
  1307. ) {
  1308. errorMessage += '<br>' + response.data.error_msg;
  1309. }
  1310. WPFormsAdmin.integrationError( errorMessage );
  1311. }
  1312. } ).fail( function() {
  1313. WPFormsAdmin.integrationError( errorMessage );
  1314. } ).complete( function() {
  1315. $btn.html( buttonLabel ).css( 'width', 'auto' ).prop( 'disabled', false );
  1316. } );
  1317. },
  1318. /**
  1319. * Remove integration provider account.
  1320. *
  1321. * @since 1.3.9
  1322. */
  1323. integrationDisconnect: function( el ) {
  1324. var $this = $( el ),
  1325. $provider = $this.parents( '.wpforms-settings-provider' ),
  1326. data = {
  1327. action : 'wpforms_settings_provider_disconnect_' + $this.data( 'provider' ),
  1328. provider: $this.data( 'provider' ),
  1329. key : $this.data( 'key' ),
  1330. nonce : wpforms_admin.nonce,
  1331. },
  1332. errorMessage = wpforms_admin.provider_delete_error;
  1333. $.confirm( {
  1334. title: wpforms_admin.heads_up,
  1335. content: wpforms_admin.provider_delete_confirm,
  1336. icon: 'fa fa-exclamation-circle',
  1337. type: 'orange',
  1338. buttons: {
  1339. confirm: {
  1340. text: wpforms_admin.ok,
  1341. btnClass: 'btn-confirm',
  1342. keys: [ 'enter' ],
  1343. action: function() {
  1344. $.post( wpforms_admin.ajax_url, data, function( response ) {
  1345. if ( response.success ) {
  1346. $this.parent().parent().remove();
  1347. // Hide Connected status label if no more integrations are linked.
  1348. var numberOfIntegrations = $provider.find( '.wpforms-settings-provider-accounts-list li' ).length;
  1349. if ( typeof numberOfIntegrations === 'undefined' || numberOfIntegrations === 0 ) {
  1350. $provider.removeClass( 'connected' );
  1351. }
  1352. } else {
  1353. if (
  1354. Object.prototype.hasOwnProperty.call( response, 'data' ) &&
  1355. Object.prototype.hasOwnProperty.call( response.data, 'error_msg' )
  1356. ) {
  1357. errorMessage += '<br>' + response.data.error_msg;
  1358. }
  1359. WPFormsAdmin.integrationError( errorMessage );
  1360. }
  1361. } ).fail( function() {
  1362. WPFormsAdmin.integrationError( errorMessage );
  1363. } );
  1364. },
  1365. },
  1366. cancel: {
  1367. text: wpforms_admin.cancel,
  1368. keys: [ 'esc' ],
  1369. },
  1370. },
  1371. } );
  1372. },
  1373. /**
  1374. * Error handling.
  1375. *
  1376. * @since 1.6.4
  1377. *
  1378. * @param {string} error Error message.
  1379. */
  1380. integrationError: function( error ) {
  1381. $.alert( {
  1382. title: false,
  1383. content: error,
  1384. icon: 'fa fa-exclamation-circle',
  1385. type: 'orange',
  1386. buttons: {
  1387. confirm: {
  1388. text: wpforms_admin.ok,
  1389. btnClass: 'btn-confirm',
  1390. keys: [ 'enter' ],
  1391. },
  1392. },
  1393. } );
  1394. },
  1395. //--------------------------------------------------------------------//
  1396. // Tools.
  1397. //--------------------------------------------------------------------//
  1398. /**
  1399. * Element bindings for Tools page.
  1400. *
  1401. * @since 1.4.2
  1402. */
  1403. initTools: function() {
  1404. // Run import for a specific provider.
  1405. $( document ).on( 'click', '#wpforms-ssl-verify', function( event ) {
  1406. event.preventDefault();
  1407. WPFormsAdmin.verifySSLConnection();
  1408. });
  1409. // Run import for a specific provider.
  1410. $( document ).on( 'click', '#wpforms-importer-forms-submit', function( event ) {
  1411. event.preventDefault();
  1412. // Check to confirm user as selected a form.
  1413. if ( $( '#wpforms-importer-forms input:checked' ).length ) {
  1414. var ids = [];
  1415. $( '#wpforms-importer-forms input:checked' ).each( function ( i ) {
  1416. ids[i] = $( this ).val();
  1417. });
  1418. if ( ! wpforms_admin.isPro ) {
  1419. // We need to analyze the forms before starting the
  1420. // actual import.
  1421. WPFormsAdmin.analyzeForms( ids );
  1422. } else {
  1423. // Begin the import process.
  1424. WPFormsAdmin.importForms( ids );
  1425. }
  1426. } else {
  1427. // User didn't actually select a form so alert them.
  1428. $.alert({
  1429. title: false,
  1430. content: wpforms_admin.importer_forms_required,
  1431. icon: 'fa fa-info-circle',
  1432. type: 'blue',
  1433. buttons: {
  1434. confirm: {
  1435. text: wpforms_admin.ok,
  1436. btnClass: 'btn-confirm',
  1437. keys: [ 'enter' ],
  1438. }
  1439. }
  1440. });
  1441. }
  1442. });
  1443. // Continue import after analyzing.
  1444. $( document ).on( 'click', '#wpforms-importer-continue-submit', function( event ) {
  1445. event.preventDefault();
  1446. WPFormsAdmin.importForms( s.formIDs );
  1447. });
  1448. },
  1449. /**
  1450. * Perform test connection to verify that the current web host
  1451. * can successfully make outbound SSL connections.
  1452. *
  1453. * @since 1.4.5
  1454. */
  1455. verifySSLConnection: function() {
  1456. var $btn = $( '#wpforms-ssl-verify' ),
  1457. btnLabel = $btn.text(),
  1458. btnWidth = $btn.outerWidth(),
  1459. $settings = $btn.parent(),
  1460. data = {
  1461. action: 'wpforms_verify_ssl',
  1462. nonce: wpforms_admin.nonce
  1463. };
  1464. $btn.css( 'width', btnWidth ).prop( 'disabled', true ).text( wpforms_admin.testing );
  1465. // Trigger AJAX to test connection
  1466. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1467. console.log( res );
  1468. // Remove any previous alerts.
  1469. $settings.find( '.wpforms-alert, .wpforms-ssl-error' ).remove();
  1470. if ( res.success ){
  1471. $btn.before( '<div class="wpforms-alert wpforms-alert-success">' + res.data.msg + '</div>' );
  1472. }
  1473. if ( ! res.success && res.data.msg ) {
  1474. $btn.before( '<div class="wpforms-alert wpforms-alert-danger">' + res.data.msg + '</div>' );
  1475. }
  1476. if ( ! res.success && res.data.debug ) {
  1477. $btn.before( '<div class="wpforms-ssl-error pre-error">' + res.data.debug + '</div>' );
  1478. }
  1479. $btn.css( 'width', btnWidth ).prop( 'disabled', false ).text( btnLabel );
  1480. });
  1481. },
  1482. /**
  1483. * Begins the process of analyzing the forms.
  1484. *
  1485. * This runs for non-Pro installs to check if any of the forms to be
  1486. * imported contain fields
  1487. * not currently available.
  1488. *
  1489. * @since 1.4.2
  1490. */
  1491. analyzeForms: function( forms ) {
  1492. var $processAnalyze = $( '#wpforms-importer-analyze' );
  1493. // Display total number of forms we have to import.
  1494. $processAnalyze.find( '.form-total' ).text( forms.length );
  1495. $processAnalyze.find( '.form-current' ).text( '1' );
  1496. // Hide the form select section.
  1497. $( '#wpforms-importer-forms' ).hide();
  1498. // Show Analyze status.
  1499. $processAnalyze.show();
  1500. // Create global analyze queue.
  1501. s.analyzeQueue = forms;
  1502. s.analyzed = 0;
  1503. s.analyzeUpgrade = [];
  1504. s.formIDs = forms;
  1505. // Analyze the first form in the queue.
  1506. WPFormsAdmin.analyzeForm();
  1507. },
  1508. /**
  1509. * Analyze a single form from the queue.
  1510. *
  1511. * @since 1.4.2
  1512. */
  1513. analyzeForm: function() {
  1514. var $analyzeSettings = $( '#wpforms-importer-analyze' ),
  1515. formID = _.first( s.analyzeQueue ),
  1516. provider = WPFormsAdmin.getQueryString( 'provider' ),
  1517. data = {
  1518. action: 'wpforms_import_form_' + provider,
  1519. analyze: 1,
  1520. form_id: formID,
  1521. nonce: wpforms_admin.nonce
  1522. };
  1523. // Trigger AJAX analyze for this form.
  1524. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1525. if ( res.success ){
  1526. if ( ! _.isEmpty( res.data.upgrade_plain ) || ! _.isEmpty( res.data.upgrade_omit ) ) {
  1527. s.analyzeUpgrade.push({
  1528. name: res.data.name,
  1529. fields: _.union( res.data.upgrade_omit, res.data.upgrade_plain )
  1530. });
  1531. }
  1532. // Remove this form ID from the queue.
  1533. s.analyzeQueue = _.without( s.analyzeQueue, formID );
  1534. s.analyzed++;
  1535. if ( _.isEmpty( s.analyzeQueue ) ) {
  1536. if ( _.isEmpty( s.analyzeUpgrade ) ) {
  1537. // Continue to import forms as no Pro fields were
  1538. // found.
  1539. WPFormsAdmin.importForms( s.formIDs );
  1540. } else {
  1541. // We found Pro fields, so alert the user.
  1542. var upgradeDetails = wp.template( 'wpforms-importer-upgrade' );
  1543. $analyzeSettings.find( '.upgrade' ).append( upgradeDetails( s.analyzeUpgrade ) );
  1544. $analyzeSettings.find( '.upgrade' ).show();
  1545. $analyzeSettings.find( '.process-analyze' ).hide();
  1546. }
  1547. } else {
  1548. // Analyze next form in the queue.
  1549. $analyzeSettings.find( '.form-current' ).text( s.analyzed+1 );
  1550. WPFormsAdmin.analyzeForm();
  1551. }
  1552. }
  1553. });
  1554. },
  1555. /**
  1556. * Begins the process of importing the forms.
  1557. *
  1558. * @since 1.4.2
  1559. */
  1560. importForms: function( forms ) {
  1561. var $processSettings = $( '#wpforms-importer-process' );
  1562. // Display total number of forms we have to import.
  1563. $processSettings.find( '.form-total' ).text( forms.length );
  1564. $processSettings.find( '.form-current' ).text( '1' );
  1565. // Hide the form select and form analyze sections.
  1566. $( '#wpforms-importer-forms, #wpforms-importer-analyze' ).hide();
  1567. // Show processing status.
  1568. $processSettings.show();
  1569. // Create global import queue.
  1570. s.importQueue = forms;
  1571. s.imported = 0;
  1572. // Import the first form in the queue.
  1573. WPFormsAdmin.importForm();
  1574. },
  1575. /**
  1576. * Imports a single form from the import queue.
  1577. *
  1578. * @since 1.4.2
  1579. */
  1580. importForm: function() {
  1581. var $processSettings = $( '#wpforms-importer-process' ),
  1582. formID = _.first( s.importQueue ),
  1583. provider = WPFormsAdmin.getQueryString( 'provider' ),
  1584. data = {
  1585. action: 'wpforms_import_form_' + provider,
  1586. form_id: formID,
  1587. nonce: wpforms_admin.nonce
  1588. };
  1589. // Trigger AJAX import for this form.
  1590. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1591. if ( res.success ){
  1592. var statusUpdate;
  1593. if ( res.data.error ) {
  1594. statusUpdate = wp.template( 'wpforms-importer-status-error' );
  1595. } else {
  1596. statusUpdate = wp.template( 'wpforms-importer-status-update' );
  1597. }
  1598. $processSettings.find( '.status' ).prepend( statusUpdate( res.data ) );
  1599. $processSettings.find( '.status' ).show();
  1600. // Remove this form ID from the queue.
  1601. s.importQueue = _.without( s.importQueue, formID );
  1602. s.imported++;
  1603. if ( _.isEmpty( s.importQueue ) ) {
  1604. $processSettings.find( '.process-count' ).hide();
  1605. $processSettings.find( '.forms-completed' ).text( s.imported );
  1606. $processSettings.find( '.process-completed' ).show();
  1607. } else {
  1608. // Import next form in the queue.
  1609. $processSettings.find( '.form-current' ).text( s.imported+1 );
  1610. WPFormsAdmin.importForm();
  1611. }
  1612. }
  1613. });
  1614. },
  1615. //--------------------------------------------------------------------//
  1616. // Upgrades (Tabs view).
  1617. //--------------------------------------------------------------------//
  1618. /**
  1619. * Element bindings for Tools page.
  1620. *
  1621. * @since 1.4.3
  1622. */
  1623. initUpgrades: function() {
  1624. // Prepare to run the v1.4.3 upgrade routine.
  1625. $( document ).on( 'click', '#wpforms-upgrade-143 button', function( event ) {
  1626. event.preventDefault();
  1627. var $this = $( this ),
  1628. buttonWidth = $this.outerWidth(),
  1629. $status = $( '#wpforms-upgrade-143 .status' ),
  1630. data = {
  1631. action: 'wpforms_upgrade_143',
  1632. nonce: wpforms_admin.nonce,
  1633. init: true,
  1634. incomplete: $this.data( 'incomplete' )
  1635. };
  1636. // Change the button to indicate we are doing initial processing.
  1637. $this.html( s.iconSpinner ).css( 'width', buttonWidth ).prop( 'disabled', true );
  1638. // Get the total number of entries, then kick off the routine.
  1639. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1640. if ( res.success ){
  1641. // Set initial values.
  1642. s.upgraded = Number( res.data.upgraded );
  1643. s.upgradeTotal = Number( res.data.total );
  1644. var percent = Math.round( ( Number( s.upgraded ) / Number( s.upgradeTotal ) ) * 100 );
  1645. // Show the status area.
  1646. $this.remove();
  1647. $status.find( '.bar' ).css( 'width', percent + '%' );
  1648. $status.show().find( '.total' ).text( s.upgradeTotal );
  1649. $status.find( '.current' ).text( s.upgraded );
  1650. $status.find( '.percent' ).text( percent + '%' );
  1651. // Begin the actual upgrade routine.
  1652. WPFormsAdmin.upgrade143();
  1653. }
  1654. });
  1655. });
  1656. },
  1657. /**
  1658. * The v1.4.3 entry fields upgrade routine.
  1659. *
  1660. * @since 1.4.3
  1661. */
  1662. upgrade143: function() {
  1663. var $status = $( '#wpforms-upgrade-143 .status' ),
  1664. data = {
  1665. action: 'wpforms_upgrade_143',
  1666. nonce: wpforms_admin.nonce,
  1667. upgraded: s.upgraded
  1668. };
  1669. // Get the total number of entries, then kick off the routine.
  1670. $.post( wpforms_admin.ajax_url, data, function( res ) {
  1671. if ( res.success ){
  1672. s.upgraded = Number( s.upgraded ) + Number( res.data.count );
  1673. var percent = Math.round( ( Number( s.upgraded ) / Number( s.upgradeTotal ) ) * 100 );
  1674. // Update progress bar.
  1675. $status.find( '.bar' ).css( 'width', percent + '%' );
  1676. if ( Number( res.data.count ) < 10 ) {
  1677. // This batch completed the upgrade routine.
  1678. $status.find( '.progress-bar' ).addClass( 'complete' );
  1679. $status.find( '.msg' ).text( wpforms_admin.upgrade_completed );
  1680. } else {
  1681. $status.find( '.current' ).text( s.upgraded );
  1682. $status.find( '.percent' ).text( percent + '%' );
  1683. // Batch the next round of entries.
  1684. WPFormsAdmin.upgrade143();
  1685. }
  1686. }
  1687. });
  1688. },
  1689. /**
  1690. * Element bindings for Flyout Menu.
  1691. *
  1692. * @since 1.5.7
  1693. */
  1694. initFlyoutMenu: function() {
  1695. // Flyout Menu Elements.
  1696. var $flyoutMenu = $( '#wpforms-flyout' );
  1697. if ( $flyoutMenu.length === 0 ) {
  1698. return;
  1699. }
  1700. var $head = $flyoutMenu.find( '.wpforms-flyout-head' ),
  1701. $sullie = $head.find( 'img' ),
  1702. menu = {
  1703. state: 'inactive',
  1704. srcInactive: $sullie.attr( 'src' ),
  1705. srcActive: $sullie.data( 'active' ),
  1706. };
  1707. // Click on the menu head icon.
  1708. $head.on( 'click', function( e ) {
  1709. e.preventDefault();
  1710. if ( menu.state === 'active' ) {
  1711. $flyoutMenu.removeClass( 'opened' );
  1712. $sullie.attr( 'src', menu.srcInactive );
  1713. menu.state = 'inactive';
  1714. } else {
  1715. $flyoutMenu.addClass( 'opened' );
  1716. $sullie.attr( 'src', menu.srcActive );
  1717. menu.state = 'active';
  1718. }
  1719. } );
  1720. // Page elements and other values.
  1721. var $wpfooter = $( '#wpfooter' );
  1722. if ( $wpfooter.length === 0 ) {
  1723. return;
  1724. }
  1725. var $overlap = $( '#wpforms-overview, #wpforms-entries-list, #wpforms-tools.wpforms-tools-tab-action-scheduler' ),
  1726. wpfooterTop = $wpfooter.offset().top,
  1727. wpfooterBottom = wpfooterTop + $wpfooter.height(),
  1728. overlapBottom = $overlap.length > 0 ? $overlap.offset().top + $overlap.height() + 85 : 0;
  1729. // Hide menu if scrolled down to the bottom of the page.
  1730. $( window ).on( 'resize scroll', _.debounce( function( e ) {
  1731. var viewTop = $( window ).scrollTop(),
  1732. viewBottom = viewTop + $( window ).height();
  1733. if ( wpfooterBottom <= viewBottom && wpfooterTop >= viewTop && overlapBottom > viewBottom ) {
  1734. $flyoutMenu.addClass( 'out' );
  1735. } else {
  1736. $flyoutMenu.removeClass( 'out' );
  1737. }
  1738. }, 50 ) );
  1739. $( window ).trigger( 'scroll' );
  1740. },
  1741. /**
  1742. * Lity improvements.
  1743. *
  1744. * @since 1.5.8
  1745. */
  1746. initLity: function() {
  1747. // Use `data-lity-srcset` opener's attribute for add srcset to full image in opened lightbox.
  1748. $( document ).on( 'lity:ready', function( event, instance ) {
  1749. var $el = instance.element(),
  1750. $opener = instance.opener(),
  1751. srcset = typeof $opener !== 'undefined' ? $opener.data( 'lity-srcset' ) : '';
  1752. if ( typeof srcset !== 'undefined' && srcset !== '' ) {
  1753. $el.find( '.lity-content img' ).attr( 'srcset', srcset );
  1754. }
  1755. } );
  1756. },
  1757. //--------------------------------------------------------------------//
  1758. // Helper functions.
  1759. //--------------------------------------------------------------------//
  1760. /**
  1761. * Return if the target nodeName is a form element.
  1762. *
  1763. * @since 1.4.0
  1764. */
  1765. isFormTypeNode: function( name ) {
  1766. name = name || false;
  1767. if ( 'TEXTAREA' === name || 'INPUT' === name || 'SELECT' === name ){
  1768. return true;
  1769. }
  1770. return false;
  1771. },
  1772. /**
  1773. * Get query string in a URL.
  1774. *
  1775. * @since 1.3.9
  1776. */
  1777. getQueryString: function( name ) {
  1778. var match = new RegExp( '[?&]' + name + '=([^&]*)' ).exec( window.location.search );
  1779. return match && decodeURIComponent( match[1].replace(/\+/g, ' ') );
  1780. },
  1781. /**
  1782. * Debug output helper.
  1783. *
  1784. * @since 1.4.4
  1785. * @param msg
  1786. */
  1787. debug: function( msg ) {
  1788. if ( WPFormsAdmin.isDebug() ) {
  1789. if ( typeof msg === 'object' || msg.constructor === Array ) {
  1790. console.log( 'WPForms Debug:' );
  1791. console.log( msg );
  1792. } else {
  1793. console.log( 'WPForms Debug: ' + msg );
  1794. }
  1795. }
  1796. },
  1797. /**
  1798. * Is debug mode.
  1799. *
  1800. * @since 1.4.4
  1801. */
  1802. isDebug: function() {
  1803. return ( window.location.hash && '#wpformsdebug' === window.location.hash );
  1804. }
  1805. };
  1806. WPFormsAdmin.init();
  1807. window.WPFormsAdmin = WPFormsAdmin;
  1808. })( jQuery );