Sin descripción

customizer.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /* global jQuery, jpSimplePaymentsStrings, confirm, _ */
  2. /* eslint no-var: 0, quote-props: 0 */
  3. ( function ( api, wp, $ ) {
  4. var $document = $( document );
  5. $document.ready( function () {
  6. $document.on( 'widget-added', function ( event, widgetContainer ) {
  7. if ( widgetContainer.is( '[id*="jetpack_simple_payments_widget"]' ) ) {
  8. initWidget( widgetContainer );
  9. }
  10. } );
  11. $document.on( 'widget-synced widget-updated', function ( event, widgetContainer ) {
  12. //this fires for all widgets, this prevent errors for non SP widgets
  13. if ( ! widgetContainer.is( '[id*="jetpack_simple_payments_widget"]' ) ) {
  14. return;
  15. }
  16. event.preventDefault();
  17. syncProductLists();
  18. var widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
  19. enableFormActions( widgetForm );
  20. updateProductImage( widgetForm );
  21. } );
  22. } );
  23. function initWidget( widgetContainer ) {
  24. var widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
  25. //Add New Button
  26. widgetForm
  27. .find( '.jetpack-simple-payments-add-product' )
  28. .on( 'click', showAddNewForm( widgetForm ) );
  29. //Edit Button
  30. widgetForm
  31. .find( '.jetpack-simple-payments-edit-product' )
  32. .on( 'click', showEditForm( widgetForm ) );
  33. //Select an Image
  34. widgetForm
  35. .find(
  36. '.jetpack-simple-payments-image-fieldset .placeholder, .jetpack-simple-payments-image > img'
  37. )
  38. .on( 'click', selectImage( widgetForm ) );
  39. //Remove Image Button
  40. widgetForm
  41. .find( '.jetpack-simple-payments-remove-image' )
  42. .on( 'click', removeImage( widgetForm ) );
  43. //Save Product button
  44. widgetForm
  45. .find( '.jetpack-simple-payments-save-product' )
  46. .on( 'click', saveChanges( widgetForm ) );
  47. //Cancel Button
  48. widgetForm
  49. .find( '.jetpack-simple-payments-cancel-form' )
  50. .on( 'click', clearForm( widgetForm ) );
  51. //Delete Selected Product
  52. widgetForm
  53. .find( '.jetpack-simple-payments-delete-product' )
  54. .on( 'click', deleteProduct( widgetForm ) );
  55. //Input, Select and Checkbox change
  56. widgetForm.find( 'select, input, textarea, checkbox' ).on(
  57. 'change input propertychange',
  58. _.debounce( function () {
  59. disableFormActions( widgetForm );
  60. }, 250 )
  61. );
  62. }
  63. function syncProductLists() {
  64. var request = wp.ajax.post( 'customize-jetpack-simple-payments-buttons-get', {
  65. 'customize-jetpack-simple-payments-nonce':
  66. api.settings.nonce[ 'customize-jetpack-simple-payments' ],
  67. customize_changeset_uuid: api.settings.changeset.uuid,
  68. } );
  69. request.done( function ( data ) {
  70. var selectedProduct = 0;
  71. $( document )
  72. .find( 'select.jetpack-simple-payments-products' )
  73. .each( function ( index, select ) {
  74. var $select = $( select );
  75. selectedProduct = $select.val();
  76. $select.find( 'option' ).remove();
  77. $select.append(
  78. $.map( data, function ( product ) {
  79. return $( '<option>', { value: product.ID, text: product.post_title } );
  80. } )
  81. );
  82. $select.val( selectedProduct );
  83. } );
  84. } );
  85. }
  86. function showForm( widgetForm ) {
  87. //reset validations
  88. widgetForm.find( '.invalid' ).removeClass( 'invalid' );
  89. //disable widget title and product selector
  90. widgetForm
  91. .find( '.jetpack-simple-payments-widget-title' )
  92. .add( '.jetpack-simple-payments-products' )
  93. //disable add and edit buttons
  94. .add( '.jetpack-simple-payments-add-product' )
  95. .add( '.jetpack-simple-payments-edit-product' )
  96. //disable save, delete and cancel until the widget update event is fired
  97. .add( '.jetpack-simple-payments-save-product' )
  98. .add( '.jetpack-simple-payments-cancel-form' )
  99. .add( '.jetpack-simple-payments-delete-product' )
  100. .attr( 'disabled', 'disabled' );
  101. //show form
  102. widgetForm.find( '.jetpack-simple-payments-form' ).show();
  103. }
  104. function hideForm( widgetForm ) {
  105. //enable widget title and product selector
  106. widgetForm
  107. .find( '.jetpack-simple-payments-widget-title' )
  108. .add( '.jetpack-simple-payments-products' )
  109. .removeAttr( 'disabled' );
  110. //hide the form
  111. widgetForm.find( '.jetpack-simple-payments-form' ).hide();
  112. }
  113. function changeFormAction( widgetForm, action ) {
  114. widgetForm.find( '.jetpack-simple-payments-form-action' ).val( action ).change();
  115. }
  116. function showAddNewForm( widgetForm ) {
  117. return function ( event ) {
  118. event.preventDefault();
  119. showForm( widgetForm );
  120. changeFormAction( widgetForm, 'add' );
  121. };
  122. }
  123. function showEditForm( widgetForm ) {
  124. return function ( event ) {
  125. event.preventDefault();
  126. showForm( widgetForm );
  127. changeFormAction( widgetForm, 'edit' );
  128. };
  129. }
  130. function clearForm( widgetForm ) {
  131. return function ( event ) {
  132. event.preventDefault();
  133. hideForm( widgetForm );
  134. widgetForm
  135. .find( '.jetpack-simple-payments-add-product, .jetpack-simple-payments-edit-product' )
  136. .attr( 'disabled', 'disabled' );
  137. changeFormAction( widgetForm, 'clear' );
  138. };
  139. }
  140. function enableFormActions( widgetForm ) {
  141. var isFormVisible = widgetForm.find( '.jetpack-simple-payments-form' ).is( ':visible' );
  142. var isProductSelectVisible = widgetForm
  143. .find( '.jetpack-simple-payments-products' )
  144. .is( ':visible' ); //areProductsVisible ?
  145. var isEdit = widgetForm.find( '.jetpack-simple-payments-form-action' ).val() === 'edit';
  146. if ( isFormVisible ) {
  147. widgetForm
  148. .find( '.jetpack-simple-payments-save-product' )
  149. .add( '.jetpack-simple-payments-cancel-form' )
  150. .removeAttr( 'disabled' );
  151. } else {
  152. widgetForm.find( '.jetpack-simple-payments-add-product' ).removeAttr( 'disabled' );
  153. }
  154. if ( isFormVisible && isEdit ) {
  155. widgetForm.find( '.jetpack-simple-payments-delete-product' ).removeAttr( 'disabled' );
  156. }
  157. if ( isProductSelectVisible && ! isFormVisible ) {
  158. widgetForm.find( '.jetpack-simple-payments-edit-product' ).removeAttr( 'disabled' );
  159. }
  160. }
  161. function disableFormActions( widgetForm ) {
  162. widgetForm
  163. .find( '.jetpack-simple-payments-add-product' )
  164. .add( '.jetpack-simple-payments-edit-product' )
  165. .add( '.jetpack-simple-payments-save-product' )
  166. .add( '.jetpack-simple-payments-cancel-form' )
  167. .add( '.jetpack-simple-payments-delete-product' )
  168. .attr( 'disabled', 'disabled' );
  169. }
  170. function selectImage( widgetForm ) {
  171. return function ( event ) {
  172. event.preventDefault();
  173. var imageContainer = widgetForm.find( '.jetpack-simple-payments-image' );
  174. var mediaFrame = new wp.media.view.MediaFrame.Select( {
  175. title: 'Choose Product Image',
  176. multiple: false,
  177. library: { type: 'image' },
  178. button: { text: 'Choose Image' },
  179. } );
  180. mediaFrame.on( 'select', function () {
  181. var selection = mediaFrame.state().get( 'selection' ).first().toJSON();
  182. //hide placeholder
  183. widgetForm.find( '.jetpack-simple-payments-image-fieldset .placeholder' ).hide();
  184. //load image from media library
  185. imageContainer.find( 'img' ).attr( 'src', selection.url ).show();
  186. //show image and remove button
  187. widgetForm.find( '.jetpack-simple-payments-image' ).show();
  188. //set hidden field for the selective refresh
  189. widgetForm.find( '.jetpack-simple-payments-form-image-id' ).val( selection.id ).change();
  190. } );
  191. mediaFrame.open();
  192. };
  193. }
  194. function removeImage( widgetForm ) {
  195. return function ( event ) {
  196. event.preventDefault();
  197. //show placeholder
  198. widgetForm.find( '.jetpack-simple-payments-image-fieldset .placeholder' ).show();
  199. //hide image and remove button
  200. widgetForm.find( '.jetpack-simple-payments-image' ).hide();
  201. //set hidden field for the selective refresh
  202. widgetForm.find( '.jetpack-simple-payments-form-image-id' ).val( '' ).change();
  203. };
  204. }
  205. function updateProductImage( widgetForm ) {
  206. var newImageId = parseInt(
  207. widgetForm.find( '.jetpack-simple-payments-form-image-id' ).val(),
  208. 10
  209. );
  210. var newImageSrc = widgetForm.find( '.jetpack-simple-payments-form-image-src' ).val();
  211. var placeholder = widgetForm.find( '.jetpack-simple-payments-image-fieldset .placeholder' );
  212. var image = widgetForm.find( '.jetpack-simple-payments-image > img' );
  213. var imageControls = widgetForm.find( '.jetpack-simple-payments-image' );
  214. if ( newImageId && newImageSrc ) {
  215. image.attr( 'src', newImageSrc );
  216. placeholder.hide();
  217. imageControls.show();
  218. } else {
  219. placeholder.show();
  220. image.removeAttr( 'src' );
  221. imageControls.hide();
  222. }
  223. }
  224. function decimalPlaces( number ) {
  225. var parts = number.split( '.' );
  226. if ( parts.length > 2 ) {
  227. return null;
  228. }
  229. return parts[ 1 ] ? parts[ 1 ].length : 0;
  230. }
  231. function isFormValid( widgetForm ) {
  232. widgetForm.find( '.invalid' ).removeClass( 'invalid' );
  233. var errors = false;
  234. var postTitle = widgetForm.find( '.jetpack-simple-payments-form-product-title' ).val();
  235. if ( ! postTitle ) {
  236. widgetForm.find( '.jetpack-simple-payments-form-product-title' ).addClass( 'invalid' );
  237. errors = true;
  238. }
  239. var productPrice = widgetForm.find( '.jetpack-simple-payments-form-product-price' ).val();
  240. if ( ! productPrice || isNaN( productPrice ) || parseFloat( productPrice ) <= 0 ) {
  241. widgetForm.find( '.jetpack-simple-payments-form-product-price' ).addClass( 'invalid' );
  242. errors = true;
  243. }
  244. // Japan's Yen is the only supported currency with a zero decimal precision.
  245. var precision =
  246. widgetForm.find( '.jetpack-simple-payments-form-product-currency' ).val() === 'JPY' ? 0 : 2;
  247. var priceDecimalPlaces = decimalPlaces( productPrice );
  248. if ( priceDecimalPlaces === null || priceDecimalPlaces > precision ) {
  249. widgetForm.find( '.jetpack-simple-payments-form-product-price' ).addClass( 'invalid' );
  250. errors = true;
  251. }
  252. var productEmail = widgetForm.find( '.jetpack-simple-payments-form-product-email' ).val();
  253. var isProductEmailValid = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(
  254. productEmail
  255. );
  256. if ( ! productEmail || ! isProductEmailValid ) {
  257. widgetForm.find( '.jetpack-simple-payments-form-product-email' ).addClass( 'invalid' );
  258. errors = true;
  259. }
  260. return ! errors;
  261. }
  262. function saveChanges( widgetForm ) {
  263. return function ( event ) {
  264. event.preventDefault();
  265. var productPostId = widgetForm.find( '.jetpack-simple-payments-form-product-id' ).val();
  266. if ( ! isFormValid( widgetForm ) ) {
  267. return;
  268. }
  269. disableFormActions( widgetForm );
  270. widgetForm.find( '.spinner' ).show();
  271. var request = wp.ajax.post( 'customize-jetpack-simple-payments-button-save', {
  272. 'customize-jetpack-simple-payments-nonce':
  273. api.settings.nonce[ 'customize-jetpack-simple-payments' ],
  274. customize_changeset_uuid: api.settings.changeset.uuid,
  275. params: {
  276. product_post_id: productPostId,
  277. post_title: widgetForm.find( '.jetpack-simple-payments-form-product-title' ).val(),
  278. post_content: widgetForm
  279. .find( '.jetpack-simple-payments-form-product-description' )
  280. .val(),
  281. image_id: widgetForm.find( '.jetpack-simple-payments-form-image-id' ).val(),
  282. currency: widgetForm.find( '.jetpack-simple-payments-form-product-currency' ).val(),
  283. price: widgetForm.find( '.jetpack-simple-payments-form-product-price' ).val(),
  284. multiple: widgetForm
  285. .find( '.jetpack-simple-payments-form-product-multiple' )
  286. .is( ':checked' )
  287. ? 1
  288. : 0,
  289. email: widgetForm.find( '.jetpack-simple-payments-form-product-email' ).val(),
  290. },
  291. } );
  292. request.done( function ( data ) {
  293. var select = widgetForm.find( 'select.jetpack-simple-payments-products' );
  294. var productOption = select.find( 'option[value="' + productPostId + '"]' );
  295. if ( productOption.length > 0 ) {
  296. productOption.text( data.product_post_title );
  297. } else {
  298. select.append(
  299. $( '<option>', {
  300. value: data.product_post_id,
  301. text: data.product_post_title,
  302. } )
  303. );
  304. select.val( data.product_post_id ).change();
  305. }
  306. widgetForm.find( '.jetpack-simple-payments-products-fieldset' ).show();
  307. widgetForm.find( '.jetpack-simple-payments-products-warning' ).hide();
  308. changeFormAction( widgetForm, 'clear' );
  309. hideForm( widgetForm );
  310. } );
  311. request.fail( function ( data ) {
  312. var validCodes = {
  313. post_title: 'product-title',
  314. price: 'product-price',
  315. email: 'product-email',
  316. };
  317. data.forEach( function ( item ) {
  318. if ( validCodes.hasOwnProperty( item.code ) ) {
  319. widgetForm
  320. .find( '.jetpack-simple-payments-form-' + validCodes[ item.code ] )
  321. .addClass( 'invalid' );
  322. }
  323. } );
  324. enableFormActions( widgetForm );
  325. } );
  326. };
  327. }
  328. function deleteProduct( widgetForm ) {
  329. return function ( event ) {
  330. event.preventDefault();
  331. if ( ! confirm( jpSimplePaymentsStrings.deleteConfirmation ) ) {
  332. return;
  333. }
  334. var formProductId = parseInt(
  335. widgetForm.find( '.jetpack-simple-payments-form-product-id' ).val(),
  336. 10
  337. );
  338. if ( ! formProductId ) {
  339. return;
  340. }
  341. disableFormActions( widgetForm );
  342. widgetForm.find( '.spinner' ).show();
  343. var request = wp.ajax.post( 'customize-jetpack-simple-payments-button-delete', {
  344. 'customize-jetpack-simple-payments-nonce':
  345. api.settings.nonce[ 'customize-jetpack-simple-payments' ],
  346. customize_changeset_uuid: api.settings.changeset.uuid,
  347. params: {
  348. product_post_id: formProductId,
  349. },
  350. } );
  351. request.done( function () {
  352. var productList = widgetForm.find( 'select.jetpack-simple-payments-products' )[ 0 ];
  353. productList.remove( productList.selectedIndex );
  354. productList.dispatchEvent( new Event( 'change' ) );
  355. if ( $( productList ).has( 'option' ).length === 0 ) {
  356. //hide products select and label
  357. widgetForm.find( '.jetpack-simple-payments-products-fieldset' ).hide();
  358. //show empty products list warning
  359. widgetForm.find( '.jetpack-simple-payments-products-warning' ).show();
  360. }
  361. changeFormAction( widgetForm, 'clear' );
  362. hideForm( widgetForm );
  363. } );
  364. };
  365. }
  366. } )( wp.customize, wp, jQuery );