Нет описания

wc-shipping-zones.js 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /* global shippingZonesLocalizeScript, ajaxurl */
  2. ( function( $, data, wp, ajaxurl ) {
  3. $( function() {
  4. var $table = $( '.wc-shipping-zones' ),
  5. $tbody = $( '.wc-shipping-zone-rows' ),
  6. $save_button = $( '.wc-shipping-zone-save' ),
  7. $row_template = wp.template( 'wc-shipping-zone-row' ),
  8. $blank_template = wp.template( 'wc-shipping-zone-row-blank' ),
  9. // Backbone model
  10. ShippingZone = Backbone.Model.extend({
  11. changes: {},
  12. logChanges: function( changedRows ) {
  13. var changes = this.changes || {};
  14. _.each( changedRows, function( row, id ) {
  15. changes[ id ] = _.extend( changes[ id ] || { zone_id : id }, row );
  16. } );
  17. this.changes = changes;
  18. this.trigger( 'change:zones' );
  19. },
  20. discardChanges: function( id ) {
  21. var changes = this.changes || {},
  22. set_position = null,
  23. zones = _.indexBy( this.get( 'zones' ), 'zone_id' );
  24. // Find current set position if it has moved since last save
  25. if ( changes[ id ] && changes[ id ].zone_order !== undefined ) {
  26. set_position = changes[ id ].zone_order;
  27. }
  28. // Delete all changes
  29. delete changes[ id ];
  30. // If the position was set, and this zone does exist in DB, set the position again so the changes are not lost.
  31. if ( set_position !== null && zones[ id ] && zones[ id ].zone_order !== set_position ) {
  32. changes[ id ] = _.extend( changes[ id ] || {}, { zone_id : id, zone_order : set_position } );
  33. }
  34. this.changes = changes;
  35. // No changes? Disable save button.
  36. if ( 0 === _.size( this.changes ) ) {
  37. shippingZoneView.clearUnloadConfirmation();
  38. }
  39. },
  40. save: function() {
  41. if ( _.size( this.changes ) ) {
  42. $.post( ajaxurl + ( ajaxurl.indexOf( '?' ) > 0 ? '&' : '?' ) + 'action=woocommerce_shipping_zones_save_changes', {
  43. wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
  44. changes : this.changes
  45. }, this.onSaveResponse, 'json' );
  46. } else {
  47. shippingZone.trigger( 'saved:zones' );
  48. }
  49. },
  50. onSaveResponse: function( response, textStatus ) {
  51. if ( 'success' === textStatus ) {
  52. if ( response.success ) {
  53. shippingZone.set( 'zones', response.data.zones );
  54. shippingZone.trigger( 'change:zones' );
  55. shippingZone.changes = {};
  56. shippingZone.trigger( 'saved:zones' );
  57. } else {
  58. window.alert( data.strings.save_failed );
  59. }
  60. }
  61. }
  62. } ),
  63. // Backbone view
  64. ShippingZoneView = Backbone.View.extend({
  65. rowTemplate: $row_template,
  66. initialize: function() {
  67. this.listenTo( this.model, 'change:zones', this.setUnloadConfirmation );
  68. this.listenTo( this.model, 'saved:zones', this.clearUnloadConfirmation );
  69. this.listenTo( this.model, 'saved:zones', this.render );
  70. $tbody.on( 'change', { view: this }, this.updateModelOnChange );
  71. $tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort );
  72. $( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
  73. $( document.body ).on( 'click', '.wc-shipping-zone-add', { view: this }, this.onAddNewRow );
  74. },
  75. onAddNewRow: function() {
  76. var $link = $( this );
  77. window.location.href = $link.attr( 'href' );
  78. },
  79. block: function() {
  80. $( this.el ).block({
  81. message: null,
  82. overlayCSS: {
  83. background: '#fff',
  84. opacity: 0.6
  85. }
  86. });
  87. },
  88. unblock: function() {
  89. $( this.el ).unblock();
  90. },
  91. render: function() {
  92. var zones = _.indexBy( this.model.get( 'zones' ), 'zone_id' ),
  93. view = this;
  94. view.$el.empty();
  95. view.unblock();
  96. if ( _.size( zones ) ) {
  97. // Sort zones
  98. zones = _( zones )
  99. .chain()
  100. .sortBy( function ( zone ) { return parseInt( zone.zone_id, 10 ); } )
  101. .sortBy( function ( zone ) { return parseInt( zone.zone_order, 10 ); } )
  102. .value();
  103. // Populate $tbody with the current zones
  104. $.each( zones, function( id, rowData ) {
  105. view.renderRow( rowData );
  106. } );
  107. } else {
  108. view.$el.append( $blank_template );
  109. }
  110. view.initRows();
  111. },
  112. renderRow: function( rowData ) {
  113. var view = this;
  114. view.$el.append( view.rowTemplate( rowData ) );
  115. view.initRow( rowData );
  116. },
  117. initRow: function( rowData ) {
  118. var view = this;
  119. var $tr = view.$el.find( 'tr[data-id="' + rowData.zone_id + '"]');
  120. // List shipping methods
  121. view.renderShippingMethods( rowData.zone_id, rowData.shipping_methods );
  122. $tr.find( '.wc-shipping-zone-delete' ).on( 'click', { view: this }, this.onDeleteRow );
  123. },
  124. initRows: function() {
  125. // Stripe
  126. if ( 0 === ( $( 'tbody.wc-shipping-zone-rows tr' ).length % 2 ) ) {
  127. $table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).addClass( 'odd' );
  128. } else {
  129. $table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).removeClass( 'odd' );
  130. }
  131. // Tooltips
  132. $( '#tiptip_holder' ).removeAttr( 'style' );
  133. $( '#tiptip_arrow' ).removeAttr( 'style' );
  134. $( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
  135. },
  136. renderShippingMethods: function( zone_id, shipping_methods ) {
  137. var $tr = $( '.wc-shipping-zones tr[data-id="' + zone_id + '"]');
  138. var $method_list = $tr.find('.wc-shipping-zone-methods ul');
  139. $method_list.find( '.wc-shipping-zone-method' ).remove();
  140. if ( _.size( shipping_methods ) ) {
  141. shipping_methods = _.sortBy( shipping_methods, function( method ) {
  142. return parseInt( method.method_order, 10 );
  143. } );
  144. _.each( shipping_methods, function( shipping_method ) {
  145. var class_name = 'method_disabled';
  146. if ( 'yes' === shipping_method.enabled ) {
  147. class_name = 'method_enabled';
  148. }
  149. $method_list.append(
  150. '<li class="wc-shipping-zone-method ' + class_name + '">' + shipping_method.title + '</li>'
  151. );
  152. } );
  153. } else {
  154. $method_list.append( '<li class="wc-shipping-zone-method">' + data.strings.no_shipping_methods_offered + '</li>' );
  155. }
  156. },
  157. onDeleteRow: function( event ) {
  158. var view = event.data.view,
  159. model = view.model,
  160. zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
  161. changes = {},
  162. row = $( this ).closest('tr'),
  163. zone_id = row.data('id');
  164. event.preventDefault();
  165. if ( window.confirm( data.strings.delete_confirmation_msg ) ) {
  166. if ( zones[ zone_id ] ) {
  167. delete zones[ zone_id ];
  168. changes[ zone_id ] = _.extend( changes[ zone_id ] || {}, { deleted : 'deleted' } );
  169. model.set( 'zones', zones );
  170. model.logChanges( changes );
  171. event.data.view.block();
  172. event.data.view.model.save();
  173. }
  174. }
  175. },
  176. setUnloadConfirmation: function() {
  177. this.needsUnloadConfirm = true;
  178. $save_button.prop( 'disabled', false );
  179. },
  180. clearUnloadConfirmation: function() {
  181. this.needsUnloadConfirm = false;
  182. $save_button.prop( 'disabled', true );
  183. },
  184. unloadConfirmation: function( event ) {
  185. if ( event.data.view.needsUnloadConfirm ) {
  186. event.returnValue = data.strings.unload_confirmation_msg;
  187. window.event.returnValue = data.strings.unload_confirmation_msg;
  188. return data.strings.unload_confirmation_msg;
  189. }
  190. },
  191. updateModelOnChange: function( event ) {
  192. var model = event.data.view.model,
  193. $target = $( event.target ),
  194. zone_id = $target.closest( 'tr' ).data( 'id' ),
  195. attribute = $target.data( 'attribute' ),
  196. value = $target.val(),
  197. zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
  198. changes = {};
  199. if ( ! zones[ zone_id ] || zones[ zone_id ][ attribute ] !== value ) {
  200. changes[ zone_id ] = {};
  201. changes[ zone_id ][ attribute ] = value;
  202. }
  203. model.logChanges( changes );
  204. },
  205. updateModelOnSort: function( event ) {
  206. var view = event.data.view,
  207. model = view.model,
  208. zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
  209. rows = $( 'tbody.wc-shipping-zone-rows tr' ),
  210. changes = {};
  211. // Update sorted row position
  212. _.each( rows, function( row ) {
  213. var zone_id = $( row ).data( 'id' ),
  214. old_position = null,
  215. new_position = parseInt( $( row ).index(), 10 );
  216. if ( zones[ zone_id ] ) {
  217. old_position = parseInt( zones[ zone_id ].zone_order, 10 );
  218. }
  219. if ( old_position !== new_position ) {
  220. changes[ zone_id ] = _.extend( changes[ zone_id ] || {}, { zone_order : new_position } );
  221. }
  222. } );
  223. if ( _.size( changes ) ) {
  224. model.logChanges( changes );
  225. event.data.view.block();
  226. event.data.view.model.save();
  227. }
  228. }
  229. } ),
  230. shippingZone = new ShippingZone({
  231. zones: data.zones
  232. } ),
  233. shippingZoneView = new ShippingZoneView({
  234. model: shippingZone,
  235. el: $tbody
  236. } );
  237. shippingZoneView.render();
  238. $tbody.sortable({
  239. items: 'tr',
  240. cursor: 'move',
  241. axis: 'y',
  242. handle: 'td.wc-shipping-zone-sort',
  243. scrollSensitivity: 40
  244. });
  245. });
  246. })( jQuery, shippingZonesLocalizeScript, wp, ajaxurl );