PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 11.1.0
WooCommerce v11.1.0
11.1.0 11.1.0-rc.2 11.1.0-rc.1 11.1.0-beta.2 11.1.0-beta.1 11.0.1 11.0.0 11.0.0-rc.3 11.0.0-rc.2 11.0.0-rc.1 11.0.0-beta.2 11.0.0-beta.1 10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / assets / js / admin / meta-boxes-order.js
woocommerce / assets / js / admin Last commit date
api-keys.js 5 years ago api-keys.min.js 3 years ago backbone-modal.js 2 weeks ago backbone-modal.min.js 2 weeks ago marketplace-suggestions.js 1 year ago marketplace-suggestions.min.js 1 year ago meta-boxes-coupon.js 1 year ago meta-boxes-coupon.min.js 1 year ago meta-boxes-order.js 2 weeks ago meta-boxes-order.min.js 2 weeks ago meta-boxes-product-variation.js 2 weeks ago meta-boxes-product-variation.min.js 2 weeks ago meta-boxes-product.js 2 weeks ago meta-boxes-product.min.js 2 weeks ago meta-boxes.js 6 months ago meta-boxes.min.js 6 months ago network-orders.js 8 years ago network-orders.min.js 3 years ago order-attribution-admin.js 2 years ago order-attribution-admin.min.js 2 years ago product-editor.js 1 year ago product-editor.min.js 1 year ago product-ordering.js 5 months ago product-ordering.min.js 5 months ago quick-edit.js 2 weeks ago quick-edit.min.js 2 weeks ago reports.js 1 year ago reports.min.js 1 year ago settings-views-html-settings-tax.js 1 month ago settings-views-html-settings-tax.min.js 1 month ago settings.js 1 year ago settings.min.js 1 year ago system-status.js 1 month ago system-status.min.js 1 month ago term-ordering.js 5 months ago term-ordering.min.js 5 months ago users.js 5 years ago users.min.js 3 years ago variation-gallery.js 2 months ago variation-gallery.min.js 2 months ago wc-admin-notices.js 2 weeks ago wc-admin-notices.min.js 2 weeks ago wc-brands-enhanced-select.js 1 year ago wc-brands-enhanced-select.min.js 1 year ago wc-clipboard.js 5 years ago wc-clipboard.min.js 5 years ago wc-customer-stock-notifications.js 1 year ago wc-customer-stock-notifications.min.js 1 year ago wc-enhanced-select.js 2 weeks ago wc-enhanced-select.min.js 2 weeks ago wc-orders.js 4 weeks ago wc-orders.min.js 4 weeks ago wc-product-export.js 1 year ago wc-product-export.min.js 1 year ago wc-product-import.js 3 years ago wc-product-import.min.js 3 years ago wc-recent-reviews-widget-async.js 6 months ago wc-recent-reviews-widget-async.min.js 6 months ago wc-setup.js 5 years ago wc-setup.min.js 3 years ago wc-shipping-classes.js 1 year ago wc-shipping-classes.min.js 1 year ago wc-shipping-providers.js 5 months ago wc-shipping-providers.min.js 5 months ago wc-shipping-zone-methods.js 2 weeks ago wc-shipping-zone-methods.min.js 2 weeks ago wc-shipping-zones.js 1 year ago wc-shipping-zones.min.js 1 year ago wc-status-widget-async.js 6 months ago wc-status-widget-async.min.js 6 months ago wc-status-widget.js 1 year ago wc-status-widget.min.js 1 year ago woocommerce_admin.js 1 month ago woocommerce_admin.min.js 1 month ago
meta-boxes-order.js
1836 lines
1 // eslint-disable-next-line max-len
2 /*global woocommerce_admin_meta_boxes, woocommerce_admin, accounting, woocommerce_admin_meta_boxes_order, wcSetClipboard, wcClearClipboard, wc_enhanced_select_params */
3
4 jQuery( function ( $ ) {
5
6 // Stand-in wcTracks.recordEvent in case tracks is not available (for any reason).
7 window.wcTracks = window.wcTracks || {};
8 window.wcTracks.recordEvent = window.wcTracks.recordEvent || function() { };
9
10 /**
11 * Order Data Panel
12 */
13 var wc_meta_boxes_order = {
14 states: null,
15 init: function() {
16 if (
17 ! (
18 typeof woocommerce_admin_meta_boxes_order === 'undefined' ||
19 typeof woocommerce_admin_meta_boxes_order.countries === 'undefined'
20 )
21 ) {
22 /* State/Country select boxes */
23 this.states = JSON.parse( woocommerce_admin_meta_boxes_order.countries.replace( /"/g, '"' ) );
24 }
25
26 $( '.js_field-country' ).selectWoo().on( 'change', this.change_country );
27 $( '.js_field-country' ).trigger( 'change', [ true ] );
28 $( document.body ).on( 'change', 'select.js_field-state', this.change_state );
29 $( '#woocommerce-order-actions input, #woocommerce-order-actions a' ).on( 'click', function() {
30 window.onbeforeunload = '';
31 });
32 $( 'a.edit_address' ).on( 'click', this.edit_address );
33 $( 'a.billing-same-as-shipping' ).on( 'click', this.copy_billing_to_shipping );
34 $( 'a.load_customer_billing' ).on( 'click', this.load_billing );
35 $( 'a.load_customer_shipping' ).on( 'click', this.load_shipping );
36 $( '#customer_user' ).on( 'change', this.change_customer_user );
37 },
38
39 change_country: function( e, stickValue ) {
40 // Check for stickValue before using it
41 if ( typeof stickValue === 'undefined' ){
42 stickValue = false;
43 }
44
45 // Prevent if we don't have the metabox data
46 if ( wc_meta_boxes_order.states === null ){
47 return;
48 }
49
50 var $this = $( this ),
51 country = $this.val(),
52 $state = $this.parents( 'div.edit_address' ).find( ':input.js_field-state' ),
53 $parent = $state.parent(),
54 stateValue = $state.val(),
55 input_name = $state.attr( 'name' ),
56 input_id = $state.attr( 'id' ),
57 value = $this.data( 'woocommerce.stickState-' + country ) ? $this.data( 'woocommerce.stickState-' + country ) : stateValue,
58 placeholder = $state.attr( 'placeholder' ),
59 $newstate;
60
61 if ( stickValue ){
62 $this.data( 'woocommerce.stickState-' + country, value );
63 }
64
65 // Remove the previous DOM element
66 $parent.show().find( '.select2-container' ).remove();
67
68 if ( ! $.isEmptyObject( wc_meta_boxes_order.states[ country ] ) ) {
69 var state = wc_meta_boxes_order.states[ country ],
70 $defaultOption = $( '<option value=""></option>' )
71 .text( woocommerce_admin_meta_boxes_order.i18n_select_state_text );
72
73 $newstate = $( '<select></select>' )
74 .prop( 'id', input_id )
75 .prop( 'name', input_name )
76 .prop( 'placeholder', placeholder )
77 .addClass( 'js_field-state select short' )
78 .append( $defaultOption );
79
80 $.each( state, function( index ) {
81 var $option = $( '<option></option>' )
82 .prop( 'value', index )
83 .text( state[ index ] );
84 if ( index === stateValue ) {
85 $option.prop( 'selected' );
86 }
87 $newstate.append( $option );
88 } );
89
90 $newstate.val( value );
91
92 $state.replaceWith( $newstate );
93
94 $newstate.show().selectWoo().hide().trigger( 'change' );
95 } else {
96 $newstate = $( '<input type="text" />' )
97 .prop( 'id', input_id )
98 .prop( 'name', input_name )
99 .prop( 'placeholder', placeholder )
100 .addClass( 'js_field-state' )
101 .val( stateValue );
102 $state.replaceWith( $newstate );
103 }
104
105 // This event has a typo - deprecated in 2.5.0
106 $( document.body ).trigger( 'contry-change.woocommerce', [country, $( this ).closest( 'div' )] );
107 $( document.body ).trigger( 'country-change.woocommerce', [country, $( this ).closest( 'div' )] );
108 },
109
110 change_state: function() {
111 // Here we will find if state value on a select has changed and stick it to the country data
112 var $this = $( this ),
113 state = $this.val(),
114 $country = $this.parents( 'div.edit_address' ).find( ':input.js_field-country' ),
115 country = $country.val();
116
117 $country.data( 'woocommerce.stickState-' + country, state );
118 },
119
120 init_tiptip: function() {
121 $( '#tiptip_holder' ).removeAttr( 'style' );
122 $( '#tiptip_arrow' ).removeAttr( 'style' );
123 $( '.tips' ).tipTip({
124 'attribute': 'data-tip',
125 'fadeIn': 50,
126 'fadeOut': 50,
127 'delay': 200,
128 'keepAlive': true
129 });
130 },
131
132 edit_address: function( e ) {
133 e.preventDefault();
134
135 var $this = $( this ),
136 $wrapper = $this.closest( '.order_data_column' ),
137 $edit_address = $wrapper.find( 'div.edit_address' ),
138 $address = $wrapper.find( 'div.address' ),
139 $country_input = $edit_address.find( '.js_field-country' ),
140 $state_input = $edit_address.find( '.js_field-state' ),
141 is_billing = Boolean( $edit_address.find( 'input[name^="_billing_"]' ).length );
142
143 $address.hide();
144 $this.parent().find( 'a' ).toggle();
145
146 if ( ! $country_input.val() ) {
147 $country_input.val( woocommerce_admin_meta_boxes_order.default_country ).trigger( 'change' );
148 $state_input.val( woocommerce_admin_meta_boxes_order.default_state ).trigger( 'change' );
149 }
150
151 $edit_address.show();
152
153 var event_name = is_billing ? 'order_edit_billing_address_click' : 'order_edit_shipping_address_click';
154 window.wcTracks.recordEvent( event_name, {
155 order_id: woocommerce_admin_meta_boxes.post_id,
156 status: $( '#order_status' ).val()
157 } );
158 },
159
160 change_customer_user: function() {
161 if ( ! $( '#_billing_country' ).val() ) {
162 $( 'a.edit_address' ).trigger( 'click' );
163 wc_meta_boxes_order.load_billing( true );
164 wc_meta_boxes_order.load_shipping( true );
165 }
166 },
167
168 load_billing: function( force ) {
169 if ( true === force || window.confirm( woocommerce_admin_meta_boxes.load_billing ) ) {
170
171 // Get user ID to load data for
172 var user_id = $( '#customer_user' ).val();
173
174 if ( ! user_id ) {
175 window.alert( woocommerce_admin_meta_boxes.no_customer_selected );
176 return false;
177 }
178
179 var data = {
180 user_id : user_id,
181 action : 'woocommerce_get_customer_details',
182 security: woocommerce_admin_meta_boxes.get_customer_details_nonce
183 };
184
185 $( this ).closest( 'div.edit_address' ).block({
186 message: null,
187 overlayCSS: {
188 background: '#fff',
189 opacity: 0.6
190 }
191 });
192
193 $.ajax({
194 url: woocommerce_admin_meta_boxes.ajax_url,
195 data: data,
196 type: 'POST',
197 success: function( response ) {
198 if ( response && response.billing ) {
199 $.each( response.billing, function( key, data ) {
200 $( ':input#_billing_' + key ).val( data ).trigger( 'change' );
201 });
202 }
203 $( 'div.edit_address' ).unblock();
204 }
205 });
206 }
207 return false;
208 },
209
210 load_shipping: function( force ) {
211 if ( true === force || window.confirm( woocommerce_admin_meta_boxes.load_shipping ) ) {
212
213 // Get user ID to load data for
214 var user_id = $( '#customer_user' ).val();
215
216 if ( ! user_id ) {
217 window.alert( woocommerce_admin_meta_boxes.no_customer_selected );
218 return false;
219 }
220
221 var data = {
222 user_id: user_id,
223 action: 'woocommerce_get_customer_details',
224 security: woocommerce_admin_meta_boxes.get_customer_details_nonce
225 };
226
227 $( this ).closest( 'div.edit_address' ).block({
228 message: null,
229 overlayCSS: {
230 background: '#fff',
231 opacity: 0.6
232 }
233 });
234
235 $.ajax({
236 url: woocommerce_admin_meta_boxes.ajax_url,
237 data: data,
238 type: 'POST',
239 success: function( response ) {
240 if ( response && response.billing ) {
241 $.each( response.shipping, function( key, data ) {
242 $( ':input#_shipping_' + key ).val( data ).trigger( 'change' );
243 });
244 }
245 $( 'div.edit_address' ).unblock();
246 }
247 });
248 }
249 return false;
250 },
251
252 copy_billing_to_shipping: function() {
253 if ( window.confirm( woocommerce_admin_meta_boxes.copy_billing ) ) {
254 $('.order_data_column :input[name^="_billing_"]').each( function() {
255 var input_name = $(this).attr('name');
256 input_name = input_name.replace( '_billing_', '_shipping_' );
257 $( ':input#' + input_name ).val( $(this).val() ).trigger( 'change' );
258 });
259 }
260 return false;
261 }
262 };
263
264 /**
265 * Order Items Panel
266 */
267 var wc_meta_boxes_order_items = {
268 init: function() {
269 this.stupidtable.init();
270
271 $( '#woocommerce-order-items' )
272 .on( 'click', 'button.add-line-item', this.add_line_item )
273 .on( 'click', 'button.add-coupon', this.add_coupon )
274 .on( 'click', 'a.remove-coupon', this.remove_coupon )
275 .on( 'click', 'button.refund-items', this.refund_items )
276 .on( 'click', '.cancel-action', this.cancel )
277 .on( 'click', '.refund-actions .cancel-action', this.track_cancel )
278 .on( 'click', 'button.add-order-item', this.add_item )
279 .on( 'click', 'button.add-order-fee', this.add_fee )
280 .on( 'click', 'button.add-order-shipping', this.add_shipping )
281 .on( 'click', 'button.add-order-tax', this.add_tax )
282 .on( 'click', 'button.save-action', this.save_line_items )
283 .on( 'click', 'a.delete-order-tax', this.delete_tax )
284 .on( 'click', 'button.calculate-action', this.recalculate )
285 .on( 'click', 'a.edit-order-item', this.edit_item )
286 .on( 'click', 'a.delete-order-item', this.delete_item )
287 .on( 'change', 'select.shipping_method', this.shipping_method_changed )
288
289 // Refunds
290 .on( 'click', '.delete_refund', this.refunds.delete_refund )
291 .on( 'click', 'button.do-api-refund, button.do-manual-refund', this.refunds.do_refund )
292 .on( 'change', '.refund input.refund_line_total, .refund input.refund_line_tax', this.refunds.input_changed )
293 .on( 'change keyup', '.wc-order-refund-items #refund_amount', this.refunds.amount_changed )
294 .on( 'change', 'input.refund_order_item_qty', this.refunds.refund_quantity_changed )
295
296 // Qty
297 .on( 'change', 'input.quantity', this.quantity_changed )
298
299 // Subtotal/total
300 .on( 'keyup change', '.split-input :input', function() {
301 var $subtotal = $( this ).parent().prev().find(':input');
302 if ( $subtotal && ( $subtotal.val() === '' || $subtotal.is( '.match-total' ) ) ) {
303 $subtotal.val( $( this ).val() ).addClass( 'match-total' );
304 }
305 })
306
307 .on( 'keyup', '.split-input :input', function() {
308 $( this ).removeClass( 'match-total' );
309 })
310
311 // Meta
312 .on( 'click', 'button.add_order_item_meta', this.item_meta.add )
313 .on( 'click', 'button.remove_order_item_meta', this.item_meta.remove )
314
315 // Reload items
316 .on( 'wc_order_items_reload', this.reload_items )
317 .on( 'wc_order_items_reloaded', this.reloaded_items );
318
319 $( document.body )
320 .on( 'wc_backbone_modal_loaded', this.backbone.init )
321 .on( 'wc_backbone_modal_response', this.backbone.response );
322 },
323
324 block: function() {
325 $( '#woocommerce-order-items' ).block({
326 message: null,
327 overlayCSS: {
328 background: '#fff',
329 opacity: 0.6
330 }
331 });
332 },
333
334 unblock: function() {
335 $( '#woocommerce-order-items' ).unblock();
336 },
337
338 filter_data: function( handle, data ) {
339 const filteredData = $( '#woocommerce-order-items' )
340 .triggerHandler(
341 `woocommerce_order_meta_box_${handle}_ajax_data`,
342 [ data ]
343 );
344
345 if ( filteredData ) {
346 return filteredData;
347 }
348
349 return data;
350 },
351
352 reload_items: function() {
353 var data = {
354 order_id: woocommerce_admin_meta_boxes.post_id,
355 action: 'woocommerce_load_order_items',
356 security: woocommerce_admin_meta_boxes.order_item_nonce
357 };
358
359 data = wc_meta_boxes_order_items.filter_data( 'reload_items', data );
360
361 wc_meta_boxes_order_items.block();
362
363 $.ajax({
364 url: woocommerce_admin_meta_boxes.ajax_url,
365 data: data,
366 type: 'POST',
367 success: function( response ) {
368 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
369 $( '#woocommerce-order-items' ).find( '.inside' ).append( response );
370 wc_meta_boxes_order_items.reloaded_items();
371 wc_meta_boxes_order_items.unblock();
372 }
373 });
374 },
375
376 reloaded_items: function() {
377 wc_meta_boxes_order.init_tiptip();
378 wc_meta_boxes_order_items.stupidtable.init();
379 },
380
381 shipping_method_changed: function() {
382 var $select = $( this );
383 var $name = $select.closest( 'tr.shipping' ).find( 'input.shipping_method_name' );
384 var title = $select.find( 'option:selected' ).text();
385 var previousTitle = $select.data( 'selected-title' ) || $select.find( 'option' ).filter( function() {
386 return this.defaultSelected;
387 } ).text();
388 var currentTitle = $name.val();
389 var defaultTitle = $name.data( 'default-shipping-title' );
390 var nextTitle = defaultTitle;
391
392 if (
393 currentTitle
394 && currentTitle !== defaultTitle
395 && currentTitle !== previousTitle
396 ) {
397 nextTitle = currentTitle;
398 } else if ( $select.val() && 'other' !== $select.val() ) {
399 nextTitle = title;
400 }
401
402 $select.data( 'selected-title', title );
403
404 if ( currentTitle !== nextTitle ) {
405 $name.val( nextTitle ).trigger( 'change' );
406 }
407 },
408
409 // When the qty is changed, increase or decrease costs
410 quantity_changed: function() {
411 var $row = $( this ).closest( 'tr.item' );
412 var qty = $( this ).val();
413 var o_qty = $( this ).attr( 'data-qty' );
414 var line_total = $( 'input.line_total', $row );
415 var line_subtotal = $( 'input.line_subtotal', $row );
416
417 // Totals
418 var unit_total = accounting.unformat( line_total.attr( 'data-total' ), woocommerce_admin.mon_decimal_point ) / o_qty;
419 line_total.val(
420 parseFloat( accounting.formatNumber( unit_total * qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
421 .toString()
422 .replace( '.', woocommerce_admin.mon_decimal_point )
423 );
424
425 var unit_subtotal = accounting.unformat( line_subtotal.attr( 'data-subtotal' ), woocommerce_admin.mon_decimal_point ) / o_qty;
426 line_subtotal.val(
427 parseFloat( accounting.formatNumber( unit_subtotal * qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
428 .toString()
429 .replace( '.', woocommerce_admin.mon_decimal_point )
430 );
431
432 // Taxes
433 $( 'input.line_tax', $row ).each( function() {
434 var $line_total_tax = $( this );
435 var tax_id = $line_total_tax.data( 'tax_id' );
436 var unit_total_tax = accounting.unformat(
437 $line_total_tax.attr( 'data-total_tax' ),
438 woocommerce_admin.mon_decimal_point
439 ) / o_qty;
440 var $line_subtotal_tax = $( 'input.line_subtotal_tax[data-tax_id="' + tax_id + '"]', $row );
441 var unit_subtotal_tax = accounting.unformat(
442 $line_subtotal_tax.attr( 'data-subtotal_tax' ),
443 woocommerce_admin.mon_decimal_point
444 ) / o_qty;
445
446 if ( 0 < unit_total_tax ) {
447 $line_total_tax.val(
448 parseFloat( accounting.formatNumber( unit_total_tax * qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
449 .toString()
450 .replace( '.', woocommerce_admin.mon_decimal_point )
451 );
452 }
453
454 if ( 0 < unit_subtotal_tax ) {
455 $line_subtotal_tax.val(
456 parseFloat( accounting.formatNumber(
457 unit_subtotal_tax * qty,
458 woocommerce_admin_meta_boxes.rounding_precision,
459 ''
460 ) )
461 .toString()
462 .replace( '.', woocommerce_admin.mon_decimal_point )
463 );
464 }
465 });
466
467 $( this ).trigger( 'quantity_changed' );
468 },
469
470 add_line_item: function() {
471 $( 'div.wc-order-add-item' ).slideDown();
472 $( 'div.wc-order-data-row-toggle' ).not( 'div.wc-order-add-item' ).slideUp();
473
474 window.wcTracks.recordEvent( 'order_edit_add_items_click', {
475 order_id: woocommerce_admin_meta_boxes.post_id,
476 status: $( '#order_status' ).val()
477 } );
478
479 return false;
480 },
481
482 add_coupon: function() {
483 window.wcTracks.recordEvent( 'order_edit_add_coupon_click', {
484 order_id: woocommerce_admin_meta_boxes.post_id,
485 status: $( '#order_status' ).val()
486 } );
487
488 var value = window.prompt( woocommerce_admin_meta_boxes.i18n_apply_coupon );
489
490 if ( null == value ) {
491 window.wcTracks.recordEvent( 'order_edit_add_coupon_cancel', {
492 order_id: woocommerce_admin_meta_boxes.post_id,
493 status: $( '#order_status' ).val()
494 } );
495 } else {
496 wc_meta_boxes_order_items.block();
497
498 var user_id = $( '#customer_user' ).val();
499 var user_email = $( '#_billing_email' ).val();
500
501 var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
502 action : 'woocommerce_add_coupon_discount',
503 dataType : 'json',
504 order_id : woocommerce_admin_meta_boxes.post_id,
505 security : woocommerce_admin_meta_boxes.order_item_nonce,
506 coupon : value,
507 user_id : user_id,
508 user_email : user_email
509 } );
510
511 data = wc_meta_boxes_order_items.filter_data( 'add_coupon', data );
512
513 $.ajax( {
514 url: woocommerce_admin_meta_boxes.ajax_url,
515 data: data,
516 type: 'POST',
517 success: function( response ) {
518 if ( response.success ) {
519 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
520 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
521
522 // Update notes.
523 const notesEl = document.querySelector( '#woocommerce-order-notes ul.order_notes' );
524 if ( notesEl && response.data && typeof response.data.notes_html === 'string' ) {
525 notesEl.outerHTML = response.data.notes_html;
526 }
527
528 wc_meta_boxes_order_items.reloaded_items();
529 wc_meta_boxes_order_items.unblock();
530 } else {
531 window.alert( response.data.error );
532 }
533 wc_meta_boxes_order_items.unblock();
534 },
535 complete: function() {
536 window.wcTracks.recordEvent( 'order_edit_added_coupon', {
537 order_id: data.order_id,
538 status: $( '#order_status' ).val()
539 } );
540 }
541 } );
542 }
543 return false;
544 },
545
546 remove_coupon: function() {
547 var $this = $( this );
548 wc_meta_boxes_order_items.block();
549
550 var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
551 action : 'woocommerce_remove_order_coupon',
552 dataType : 'json',
553 order_id : woocommerce_admin_meta_boxes.post_id,
554 security : woocommerce_admin_meta_boxes.order_item_nonce,
555 coupon : $this.data( 'code' )
556 } );
557
558 data = wc_meta_boxes_order_items.filter_data( 'remove_coupon', data );
559
560 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
561 if ( response.success ) {
562 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
563 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
564
565 // Update notes.
566 if ( response.data.notes_html ) {
567 $( 'ul.order_notes' ).empty();
568 $( 'ul.order_notes' ).append( $( response.data.notes_html ).find( 'li' ) );
569 }
570
571 wc_meta_boxes_order_items.reloaded_items();
572 wc_meta_boxes_order_items.unblock();
573 } else {
574 window.alert( response.data.error );
575 }
576 wc_meta_boxes_order_items.unblock();
577 });
578 },
579
580 refund_items: function() {
581 $( 'div.wc-order-refund-items' ).slideDown();
582 $( 'div.wc-order-data-row-toggle' ).not( 'div.wc-order-refund-items' ).slideUp();
583 $( 'div.wc-order-totals-items' ).slideUp();
584 $( '#woocommerce-order-items' ).find( 'div.refund' ).show();
585 $( '.wc-order-edit-line-item .wc-order-edit-line-item-actions' ).hide();
586
587 window.wcTracks.recordEvent( 'order_edit_refund_button_click', {
588 order_id: woocommerce_admin_meta_boxes.post_id,
589 status: $( '#order_status' ).val()
590 } );
591
592 return false;
593 },
594
595 cancel: function() {
596 $( 'div.wc-order-data-row-toggle' ).not( 'div.wc-order-bulk-actions' ).slideUp();
597 $( 'div.wc-order-bulk-actions' ).slideDown();
598 $( 'div.wc-order-totals-items' ).slideDown();
599 $( '#woocommerce-order-items' ).find( 'div.refund' ).hide();
600 $( '.wc-order-edit-line-item .wc-order-edit-line-item-actions' ).show();
601
602 // Reload the items
603 if ( 'true' === $( this ).attr( 'data-reload' ) ) {
604 wc_meta_boxes_order_items.reload_items();
605 }
606
607 window.wcTracks.recordEvent( 'order_edit_add_items_cancelled', {
608 order_id: woocommerce_admin_meta_boxes.post_id,
609 status: $( '#order_status' ).val()
610 } );
611
612 return false;
613 },
614
615 track_cancel: function() {
616 window.wcTracks.recordEvent( 'order_edit_refund_cancel', {
617 order_id: woocommerce_admin_meta_boxes.post_id,
618 status: $( '#order_status' ).val()
619 } );
620 },
621
622 add_item: function() {
623 $( this ).WCBackboneModal({
624 template: 'wc-modal-add-products'
625 });
626
627 return false;
628 },
629
630 add_fee: function() {
631 window.wcTracks.recordEvent( 'order_edit_add_fee_click', {
632 order_id: woocommerce_admin_meta_boxes.post_id,
633 status: $( '#order_status' ).val()
634 } );
635
636 var value = window.prompt( woocommerce_admin_meta_boxes.i18n_add_fee );
637
638 if ( null == value ) {
639 window.wcTracks.recordEvent( 'order_edit_add_fee_cancel', {
640 order_id: woocommerce_admin_meta_boxes.post_id,
641 status: $( '#order_status' ).val()
642 } );
643 } else {
644 wc_meta_boxes_order_items.block();
645
646 var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
647 action : 'woocommerce_add_order_fee',
648 dataType: 'json',
649 order_id: woocommerce_admin_meta_boxes.post_id,
650 security: woocommerce_admin_meta_boxes.order_item_nonce,
651 amount : value
652 } );
653
654 data = wc_meta_boxes_order_items.filter_data( 'add_fee', data );
655
656 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
657 if ( response.success ) {
658 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
659 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
660 wc_meta_boxes_order_items.reloaded_items();
661 wc_meta_boxes_order_items.unblock();
662 window.wcTracks.recordEvent( 'order_edit_added_fee', {
663 order_id: woocommerce_admin_meta_boxes.post_id,
664 status: $( '#order_status' ).val()
665 } );
666 } else {
667 window.alert( response.data.error );
668 }
669 wc_meta_boxes_order.init_tiptip();
670 wc_meta_boxes_order_items.unblock();
671 });
672 }
673 return false;
674 },
675
676 add_shipping: function() {
677 wc_meta_boxes_order_items.block();
678
679 var data = {
680 action : 'woocommerce_add_order_shipping',
681 order_id : woocommerce_admin_meta_boxes.post_id,
682 security : woocommerce_admin_meta_boxes.order_item_nonce,
683 dataType : 'json'
684 };
685
686 data = wc_meta_boxes_order_items.filter_data( 'add_shipping', data );
687
688 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
689 if ( response.success ) {
690 $( 'table.woocommerce_order_items tbody#order_shipping_line_items' ).append( response.data.html );
691 window.wcTracks.recordEvent( 'order_edit_add_shipping', {
692 order_id: woocommerce_admin_meta_boxes.post_id,
693 status: $( '#order_status' ).val()
694 } );
695 } else {
696 window.alert( response.data.error );
697 }
698 wc_meta_boxes_order.init_tiptip();
699 wc_meta_boxes_order_items.unblock();
700 });
701
702 return false;
703 },
704
705 add_tax: function() {
706 $( this ).WCBackboneModal({
707 template: 'wc-modal-add-tax'
708 });
709 return false;
710 },
711
712 edit_item: function() {
713 $( this ).closest( 'tr' ).find( '.view' ).hide();
714 $( this ).closest( 'tr' ).find( '.edit' ).show();
715 $( this ).hide();
716 $( 'button.add-line-item' ).trigger( 'click' );
717 $( 'button.cancel-action' ).attr( 'data-reload', true );
718 window.wcTracks.recordEvent( 'order_edit_edit_item_click', {
719 order_id: woocommerce_admin_meta_boxes.post_id,
720 status: $( '#order_status' ).val()
721 } );
722 return false;
723 },
724
725 delete_item: function() {
726 var notice = woocommerce_admin_meta_boxes.remove_item_notice;
727
728 if ( $( this ).parents( 'tbody#order_fee_line_items' ).length ) {
729 notice = woocommerce_admin_meta_boxes.remove_fee_notice;
730 }
731
732 if ( $( this ).parents( 'tbody#order_shipping_line_items' ).length ) {
733 notice = woocommerce_admin_meta_boxes.remove_shipping_notice;
734 }
735
736 var answer = window.confirm( notice );
737
738 if ( answer ) {
739 var $item = $( this ).closest( 'tr.item, tr.fee, tr.shipping' );
740 var order_item_id = $item.attr( 'data-order_item_id' );
741
742 wc_meta_boxes_order_items.block();
743
744 var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
745 order_id : woocommerce_admin_meta_boxes.post_id,
746 order_item_ids: order_item_id,
747 action : 'woocommerce_remove_order_item',
748 security : woocommerce_admin_meta_boxes.order_item_nonce
749 } );
750
751 // Check if items have changed, if so pass them through so we can save them before deleting.
752 if ( 'true' === $( 'button.cancel-action' ).attr( 'data-reload' ) ) {
753 data.items = $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize();
754 }
755
756 data = wc_meta_boxes_order_items.filter_data( 'delete_item', data );
757
758 $.ajax({
759 url: woocommerce_admin_meta_boxes.ajax_url,
760 data: data,
761 type: 'POST',
762 success: function( response ) {
763 if ( response.success ) {
764 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
765 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
766
767 // Update notes.
768 const notesEl = document.querySelector( '#woocommerce-order-notes ul.order_notes' );
769 if ( notesEl && response.data && typeof response.data.notes_html === 'string' ) {
770 notesEl.outerHTML = response.data.notes_html;
771 }
772
773 wc_meta_boxes_order_items.reloaded_items();
774 wc_meta_boxes_order_items.unblock();
775 } else {
776 window.alert( response.data.error );
777 }
778 wc_meta_boxes_order_items.unblock();
779 },
780 complete: function() {
781 window.wcTracks.recordEvent( 'order_edit_remove_item', {
782 order_id: woocommerce_admin_meta_boxes.post_id,
783 status: $( '#order_status' ).val()
784 } );
785 }
786 });
787 }
788 return false;
789 },
790
791 delete_tax: function() {
792 if ( window.confirm( woocommerce_admin_meta_boxes.i18n_delete_tax ) ) {
793 wc_meta_boxes_order_items.block();
794
795 var data = {
796 action: 'woocommerce_remove_order_tax',
797 rate_id: $( this ).attr( 'data-rate_id' ),
798 order_id: woocommerce_admin_meta_boxes.post_id,
799 security: woocommerce_admin_meta_boxes.order_item_nonce
800 };
801
802 data = wc_meta_boxes_order_items.filter_data( 'delete_tax', data );
803
804 $.ajax({
805 url: woocommerce_admin_meta_boxes.ajax_url,
806 data: data,
807 type: 'POST',
808 success: function( response ) {
809 if ( response.success ) {
810 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
811 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
812 wc_meta_boxes_order_items.reloaded_items();
813 wc_meta_boxes_order_items.unblock();
814 } else {
815 window.alert( response.data.error );
816 }
817 wc_meta_boxes_order_items.unblock();
818 },
819 complete: function() {
820 window.wcTracks.recordEvent( 'order_edit_delete_tax', {
821 order_id: data.order_id,
822 status: $( '#order_status' ).val()
823 } );
824 }
825 });
826 } else {
827 window.wcTracks.recordEvent( 'order_edit_delete_tax_cancel', {
828 order_id: woocommerce_admin_meta_boxes.post_id,
829 status: $( '#order_status' ).val()
830 } );
831 }
832 return false;
833 },
834
835 get_taxable_address: function() {
836 var country = '';
837 var state = '';
838 var postcode = '';
839 var city = '';
840
841 if ( 'shipping' === woocommerce_admin_meta_boxes.tax_based_on ) {
842 country = $( '#_shipping_country' ).val();
843 state = $( '#_shipping_state' ).val();
844 postcode = $( '#_shipping_postcode' ).val();
845 city = $( '#_shipping_city' ).val();
846 }
847
848 if ( 'billing' === woocommerce_admin_meta_boxes.tax_based_on || ! country ) {
849 country = $( '#_billing_country' ).val();
850 state = $( '#_billing_state' ).val();
851 postcode = $( '#_billing_postcode' ).val();
852 city = $( '#_billing_city' ).val();
853 }
854
855 return {
856 country: country,
857 state: state,
858 postcode: postcode,
859 city: city
860 };
861 },
862
863 recalculate: function() {
864 if ( window.confirm( woocommerce_admin_meta_boxes.calc_totals ) ) {
865 wc_meta_boxes_order_items.block();
866
867 var data = $.extend( {}, wc_meta_boxes_order_items.get_taxable_address(), {
868 action: 'woocommerce_calc_line_taxes',
869 order_id: woocommerce_admin_meta_boxes.post_id,
870 items: $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize(),
871 security: woocommerce_admin_meta_boxes.calc_totals_nonce
872 } );
873
874 data = wc_meta_boxes_order_items.filter_data( 'recalculate', data );
875
876 $( document.body ).trigger( 'order-totals-recalculate-before', data );
877
878 $.ajax({
879 url: woocommerce_admin_meta_boxes.ajax_url,
880 data: data,
881 type: 'POST',
882 success: function( response ) {
883 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
884 $( '#woocommerce-order-items' ).find( '.inside' ).append( response );
885 wc_meta_boxes_order_items.reloaded_items();
886 wc_meta_boxes_order_items.unblock();
887
888 $( document.body ).trigger( 'order-totals-recalculate-success', response );
889 },
890 complete: function( response ) {
891 $( document.body ).trigger( 'order-totals-recalculate-complete', response );
892
893 window.wcTracks.recordEvent( 'order_edit_recalc_totals', {
894 order_id: woocommerce_admin_meta_boxes.post_id,
895 ok_cancel: 'OK',
896 status: $( '#order_status' ).val()
897 } );
898 }
899 });
900 } else {
901 window.wcTracks.recordEvent( 'order_edit_recalc_totals', {
902 order_id: woocommerce_admin_meta_boxes.post_id,
903 ok_cancel: 'cancel',
904 status: $( '#order_status' ).val()
905 } );
906 }
907
908 return false;
909 },
910
911 save_line_items: function() {
912 var data = {
913 order_id: woocommerce_admin_meta_boxes.post_id,
914 items: $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize(),
915 action: 'woocommerce_save_order_items',
916 security: woocommerce_admin_meta_boxes.order_item_nonce
917 };
918
919 data = wc_meta_boxes_order_items.filter_data( 'save_line_items', data );
920
921 wc_meta_boxes_order_items.block();
922
923 $.ajax({
924 url: woocommerce_admin_meta_boxes.ajax_url,
925 data: data,
926 type: 'POST',
927 success: function( response ) {
928 if ( response.success ) {
929 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
930 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
931
932 // Update notes.
933 if ( response.data.notes_html ) {
934 $( 'ul.order_notes' ).empty();
935 $( 'ul.order_notes' ).append( $( response.data.notes_html ).find( 'li' ) );
936 }
937
938 wc_meta_boxes_order_items.reloaded_items();
939 wc_meta_boxes_order_items.unblock();
940 } else {
941 wc_meta_boxes_order_items.unblock();
942 window.alert( response.data.error );
943 }
944 },
945 complete: function() {
946 window.wcTracks.recordEvent( 'order_edit_save_line_items', {
947 order_id: woocommerce_admin_meta_boxes.post_id,
948 status: $( '#order_status' ).val()
949 } );
950 }
951 });
952
953 $( this ).trigger( 'items_saved' );
954
955 return false;
956 },
957
958 refunds: {
959
960 do_refund: function() {
961 wc_meta_boxes_order_items.block();
962
963 if ( window.confirm( woocommerce_admin_meta_boxes.i18n_do_refund ) ) {
964 var refund_amount = $( 'input#refund_amount' ).val();
965 var refund_reason = $( 'input#refund_reason' ).val();
966 var refunded_amount = $( 'input#refunded_amount' ).val();
967
968 // Get line item refunds
969 var line_item_qtys = {};
970 var line_item_totals = {};
971 var line_item_tax_totals = {};
972
973 $( '.refund input.refund_order_item_qty' ).each(function( index, item ) {
974 if ( $( item ).closest( 'tr' ).data( 'order_item_id' ) ) {
975 if ( item.value ) {
976 line_item_qtys[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = item.value;
977 }
978 }
979 });
980
981 $( '.refund input.refund_line_total' ).each(function( index, item ) {
982 if ( $( item ).closest( 'tr' ).data( 'order_item_id' ) ) {
983 line_item_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = accounting.unformat(
984 item.value,
985 woocommerce_admin.mon_decimal_point
986 );
987 }
988 });
989
990 $( '.refund input.refund_line_tax' ).each(function( index, item ) {
991 if ( $( item ).closest( 'tr' ).data( 'order_item_id' ) ) {
992 var tax_id = $( item ).data( 'tax_id' );
993
994 if ( ! line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] ) {
995 line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ] = {};
996 }
997
998 line_item_tax_totals[ $( item ).closest( 'tr' ).data( 'order_item_id' ) ][ tax_id ] = accounting.unformat(
999 item.value,
1000 woocommerce_admin.mon_decimal_point
1001 );
1002 }
1003 });
1004
1005 var data = {
1006 action : 'woocommerce_refund_line_items',
1007 order_id : woocommerce_admin_meta_boxes.post_id,
1008 refund_amount : refund_amount,
1009 refunded_amount : refunded_amount,
1010 refund_reason : refund_reason,
1011 line_item_qtys : JSON.stringify( line_item_qtys, null, '' ),
1012 line_item_totals : JSON.stringify( line_item_totals, null, '' ),
1013 line_item_tax_totals : JSON.stringify( line_item_tax_totals, null, '' ),
1014 api_refund : $( this ).is( '.do-api-refund' ),
1015 restock_refunded_items: $( '#restock_refunded_items:checked' ).length ? 'true': 'false',
1016 security : woocommerce_admin_meta_boxes.order_item_nonce
1017 };
1018
1019 data = wc_meta_boxes_order_items.filter_data( 'do_refund', data );
1020
1021 $.ajax( {
1022 url: woocommerce_admin_meta_boxes.ajax_url,
1023 data: data,
1024 type: 'POST',
1025 success: function( response ) {
1026 if ( true === response.success ) {
1027 // Redirect to same page for show the refunded status
1028 window.location.reload();
1029 } else {
1030 window.alert( response.data.error );
1031 wc_meta_boxes_order_items.reload_items();
1032 wc_meta_boxes_order_items.unblock();
1033 }
1034 },
1035 complete: function() {
1036 window.wcTracks.recordEvent( 'order_edit_refunded', {
1037 order_id: data.order_id,
1038 status: $( '#order_status' ).val(),
1039 api_refund: data.api_refund,
1040 has_reason: Boolean( data.refund_reason.length ),
1041 restock: 'true' === data.restock_refunded_items
1042 } );
1043 }
1044 } );
1045 } else {
1046 wc_meta_boxes_order_items.unblock();
1047 }
1048 },
1049
1050 delete_refund: function() {
1051 if ( window.confirm( woocommerce_admin_meta_boxes.i18n_delete_refund ) ) {
1052 var $refund = $( this ).closest( 'tr.refund' );
1053 var refund_id = $refund.attr( 'data-order_refund_id' );
1054
1055 wc_meta_boxes_order_items.block();
1056
1057 var data = {
1058 action: 'woocommerce_delete_refund',
1059 refund_id: refund_id,
1060 security: woocommerce_admin_meta_boxes.order_item_nonce
1061 };
1062
1063 data = wc_meta_boxes_order_items.filter_data( 'delete_refund', data );
1064
1065 $.ajax({
1066 url: woocommerce_admin_meta_boxes.ajax_url,
1067 data: data,
1068 type: 'POST',
1069 success: function() {
1070 wc_meta_boxes_order_items.reload_items();
1071 }
1072 });
1073 }
1074 return false;
1075 },
1076
1077 input_changed: function() {
1078 var refund_amount = 0;
1079 var $items = $( '.woocommerce_order_items' ).find( 'tr.item, tr.fee, tr.shipping' );
1080 var round_at_subtotal = 'yes' === woocommerce_admin_meta_boxes.round_at_subtotal;
1081
1082 $items.each(function() {
1083 var $row = $( this );
1084 var refund_cost_fields = $row.find( '.refund input:not(.refund_order_item_qty)' );
1085
1086 refund_cost_fields.each(function( index, el ) {
1087 var field_amount = accounting.unformat( $( el ).val() || 0, woocommerce_admin.mon_decimal_point );
1088 refund_amount += parseFloat( round_at_subtotal ?
1089 field_amount :
1090 accounting.formatNumber( field_amount, woocommerce_admin_meta_boxes.currency_format_num_decimals, '' ) );
1091 });
1092 });
1093
1094 $( '#refund_amount' )
1095 .val( accounting.formatNumber(
1096 refund_amount,
1097 woocommerce_admin_meta_boxes.currency_format_num_decimals,
1098 '',
1099 woocommerce_admin.mon_decimal_point
1100 ) )
1101 .trigger( 'change' );
1102 },
1103
1104 amount_changed: function() {
1105 var total = accounting.unformat( $( this ).val(), woocommerce_admin.mon_decimal_point );
1106
1107 $( 'button .wc-order-refund-amount .amount' ).text( accounting.formatMoney( total, {
1108 symbol: woocommerce_admin_meta_boxes.currency_format_symbol,
1109 decimal: woocommerce_admin_meta_boxes.currency_format_decimal_sep,
1110 thousand: woocommerce_admin_meta_boxes.currency_format_thousand_sep,
1111 precision: woocommerce_admin_meta_boxes.currency_format_num_decimals,
1112 format: woocommerce_admin_meta_boxes.currency_format
1113 } ) );
1114 },
1115
1116 // When the refund qty is changed, increase or decrease costs
1117 refund_quantity_changed: function() {
1118 var $row = $( this ).closest( 'tr.item' );
1119 var qty = $row.find( 'input.quantity' ).val();
1120 var refund_qty = $( this ).val();
1121 var line_total = $( 'input.line_total', $row );
1122 var refund_line_total = $( 'input.refund_line_total', $row );
1123
1124 // Totals
1125 var unit_total = accounting.unformat( line_total.attr( 'data-total' ), woocommerce_admin.mon_decimal_point ) / qty;
1126
1127 refund_line_total.val(
1128 parseFloat( accounting.formatNumber( unit_total * refund_qty, woocommerce_admin_meta_boxes.rounding_precision, '' ) )
1129 .toString()
1130 .replace( '.', woocommerce_admin.mon_decimal_point )
1131 ).trigger( 'change' );
1132
1133 // Taxes
1134 $( '.refund_line_tax', $row ).each( function() {
1135 var $refund_line_total_tax = $( this );
1136 var tax_id = $refund_line_total_tax.data( 'tax_id' );
1137 var line_total_tax = $( 'input.line_tax[data-tax_id="' + tax_id + '"]', $row );
1138 var unit_total_tax = accounting.unformat(
1139 line_total_tax.data( 'total_tax' ),
1140 woocommerce_admin.mon_decimal_point
1141 ) / qty;
1142
1143 if ( 0 < unit_total_tax ) {
1144
1145 $refund_line_total_tax.val(
1146 parseFloat( accounting.formatNumber(
1147 unit_total_tax * refund_qty,
1148 woocommerce_admin_meta_boxes.rounding_precision,
1149 ''
1150 ) )
1151 .toString()
1152 .replace( '.', woocommerce_admin.mon_decimal_point )
1153 ).trigger( 'change' );
1154 } else {
1155 $refund_line_total_tax.val( 0 ).trigger( 'change' );
1156 }
1157 });
1158
1159 // Restock checkbox
1160 if ( refund_qty > 0 ) {
1161 $( '#restock_refunded_items' ).closest( 'tr' ).show();
1162 } else {
1163 $( '#restock_refunded_items' ).closest( 'tr' ).hide();
1164 $( '.woocommerce_order_items input.refund_order_item_qty' ).each( function() {
1165 if ( $( this ).val() > 0 ) {
1166 $( '#restock_refunded_items' ).closest( 'tr' ).show();
1167 }
1168 });
1169 }
1170
1171 $( this ).trigger( 'refund_quantity_changed' );
1172 }
1173 },
1174
1175 item_meta: {
1176
1177 add: function() {
1178 var $button = $( this );
1179 var $item = $button.closest( 'tr.item, tr.shipping' );
1180 var $items = $item.find('tbody.meta_items');
1181 var index = $items.find('tr').length + 1;
1182 var $row = '<tr data-meta_id="0">' +
1183 '<td>' +
1184 '<input type="text" maxlength="255" placeholder="' +
1185 woocommerce_admin_meta_boxes_order.placeholder_name +
1186 '" name="meta_key[' + $item.attr( 'data-order_item_id' ) +
1187 '][new-' + index + ']" />' +
1188 '<textarea placeholder="' +
1189 woocommerce_admin_meta_boxes_order.placeholder_value +
1190 '" name="meta_value[' +
1191 $item.attr( 'data-order_item_id' ) +
1192 '][new-' +
1193 index +
1194 ']"></textarea>' +
1195 '</td>' +
1196 '<td width="1%"><button class="remove_order_item_meta button">&times;</button></td>' +
1197 '</tr>';
1198 $items.append( $row );
1199
1200 return false;
1201 },
1202
1203 remove: function() {
1204 if ( window.confirm( woocommerce_admin_meta_boxes.remove_item_meta ) ) {
1205 var $row = $( this ).closest( 'tr' );
1206 $row.find( ':input' ).val( '' );
1207 $row.hide();
1208 }
1209 return false;
1210 }
1211 },
1212
1213 backbone: {
1214
1215 init: function( e, target ) {
1216 if ( 'wc-modal-add-products' === target ) {
1217 $( document.body ).trigger( 'wc-enhanced-select-init' );
1218
1219 $( this ).on( 'change', '.wc-product-search', function() {
1220 if ( ! $( this ).closest( 'tr' ).is( ':last-child' ) ) {
1221 return;
1222 }
1223 var item_table = $( this ).closest( 'table.widefat' ),
1224 item_table_body = item_table.find( 'tbody' ),
1225 index = item_table_body.find( 'tr' ).length,
1226 row = item_table_body.data( 'row' ).replace( /\[0\]/g, '[' + index + ']' );
1227
1228 item_table_body.append( '<tr>' + row + '</tr>' );
1229 $( document.body ).trigger( 'wc-enhanced-select-init' );
1230 } );
1231 }
1232 },
1233
1234 response: function( e, target, data ) {
1235 if ( 'wc-modal-add-tax' === target ) {
1236 var rate_id = data.add_order_tax;
1237 var manual_rate_id = '';
1238
1239 if ( data.manual_tax_rate_id ) {
1240 manual_rate_id = data.manual_tax_rate_id;
1241 }
1242
1243 wc_meta_boxes_order_items.backbone.add_tax( rate_id, manual_rate_id );
1244 }
1245 if ( 'wc-modal-add-products' === target ) {
1246 // Build array of data.
1247 var item_table = $( this ).find( 'table.widefat' ),
1248 item_table_body = item_table.find( 'tbody' ),
1249 rows = item_table_body.find( 'tr' ),
1250 add_items = [];
1251
1252 $( rows ).each( function() {
1253 var item_id = $( this ).find( ':input[name="item_id"]' ).val(),
1254 item_qty = $( this ).find( ':input[name="item_qty"]' ).val();
1255
1256 add_items.push( {
1257 'id' : item_id,
1258 'qty': item_qty ? item_qty: 1
1259 } );
1260 } );
1261
1262 return wc_meta_boxes_order_items.backbone.add_items( add_items );
1263 }
1264 },
1265
1266 add_items: function( add_items ) {
1267 wc_meta_boxes_order_items.block();
1268
1269 var data = {
1270 action : 'woocommerce_add_order_item',
1271 order_id : woocommerce_admin_meta_boxes.post_id,
1272 security : woocommerce_admin_meta_boxes.order_item_nonce,
1273 data : add_items
1274 };
1275
1276 // Check if items have changed, if so pass them through so we can save them before adding a new item.
1277 if ( 'true' === $( 'button.cancel-action' ).attr( 'data-reload' ) ) {
1278 data.items = $( 'table.woocommerce_order_items :input[name], .wc-order-totals-items :input[name]' ).serialize();
1279 }
1280
1281 data = wc_meta_boxes_order_items.filter_data( 'add_items', data );
1282
1283 $.ajax({
1284 type: 'POST',
1285 url: woocommerce_admin_meta_boxes.ajax_url,
1286 data: data,
1287 success: function( response ) {
1288 if ( response.success ) {
1289 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
1290 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
1291
1292 // Update notes.
1293 const notesEl = document.querySelector( '#woocommerce-order-notes ul.order_notes' );
1294 if ( notesEl && response.data && typeof response.data.notes_html === 'string' ) {
1295 notesEl.outerHTML = response.data.notes_html;
1296 }
1297
1298 wc_meta_boxes_order_items.reloaded_items();
1299 wc_meta_boxes_order_items.unblock();
1300 } else {
1301 wc_meta_boxes_order_items.unblock();
1302 window.alert( response.data.error );
1303 }
1304 },
1305 complete: function() {
1306 window.wcTracks.recordEvent( 'order_edit_add_products', {
1307 order_id: woocommerce_admin_meta_boxes.post_id,
1308 status: $( '#order_status' ).val()
1309 } );
1310 },
1311 dataType: 'json'
1312 });
1313 },
1314
1315 add_tax: function( rate_id, manual_rate_id ) {
1316 if ( manual_rate_id ) {
1317 rate_id = manual_rate_id;
1318 }
1319
1320 if ( ! rate_id ) {
1321 return false;
1322 }
1323
1324 var rates = $( '.order-tax-id' ).map( function() {
1325 return $( this ).val();
1326 }).get();
1327
1328 // Test if already exists
1329 if ( -1 === $.inArray( rate_id, rates ) ) {
1330 wc_meta_boxes_order_items.block();
1331
1332 var data = {
1333 action: 'woocommerce_add_order_tax',
1334 rate_id: rate_id,
1335 order_id: woocommerce_admin_meta_boxes.post_id,
1336 security: woocommerce_admin_meta_boxes.order_item_nonce
1337 };
1338
1339 data = wc_meta_boxes_order_items.filter_data( 'add_tax', data );
1340
1341 $.ajax({
1342 url : woocommerce_admin_meta_boxes.ajax_url,
1343 data : data,
1344 dataType : 'json',
1345 type : 'POST',
1346 success : function( response ) {
1347 if ( response.success ) {
1348 $( '#woocommerce-order-items' ).find( '.inside' ).empty();
1349 $( '#woocommerce-order-items' ).find( '.inside' ).append( response.data.html );
1350 wc_meta_boxes_order_items.reloaded_items();
1351 } else {
1352 window.alert( response.data.error );
1353 }
1354 wc_meta_boxes_order_items.unblock();
1355 },
1356 complete: function() {
1357 window.wcTracks.recordEvent( 'order_edit_add_tax', {
1358 order_id: woocommerce_admin_meta_boxes.post_id,
1359 status: $( '#order_status' ).val()
1360 } );
1361 }
1362 });
1363 } else {
1364 window.alert( woocommerce_admin_meta_boxes.i18n_tax_rate_already_exists );
1365 }
1366 }
1367 },
1368
1369 stupidtable: {
1370 init: function() {
1371 $( '.woocommerce_order_items' ).stupidtable();
1372 $( '.woocommerce_order_items' ).on( 'aftertablesort', this.add_arrows );
1373 },
1374
1375 add_arrows: function( event, data ) {
1376 var th = $( this ).find( 'th' );
1377 var arrow = data.direction === 'asc' ? '&uarr;' : '&darr;';
1378 var index = data.column;
1379 th.find( '.wc-arrow' ).remove();
1380 th.eq( index ).append( '<span class="wc-arrow">' + arrow + '</span>' );
1381 }
1382 }
1383 };
1384
1385 /**
1386 * Order Notes Panel
1387 */
1388 var wc_meta_boxes_order_notes = {
1389 init: function() {
1390 $( '#woocommerce-order-notes' )
1391 .on( 'click', 'button.add_note', this.add_order_note )
1392 .on( 'click', 'a.delete_note', this.delete_order_note )
1393 .on( 'change', 'select#order_note_type', this.update_note_type_ui );
1394
1395 // Sync the CTA + helper link to reflect the current select state on load.
1396 $( 'select#order_note_type' ).trigger( 'change' );
1397 },
1398
1399 update_note_type_ui: function() {
1400 var $option = $( this ).find( ':selected' );
1401 // Fallback: extension-injected options may lack data-button-label.
1402 // Default to the first option's label so the button never shows stale text.
1403 var defaultLabel = $( this ).find( 'option:first' ).data( 'button-label' );
1404 var label = $option.data( 'button-label' ) || defaultLabel;
1405 var isCustomer = 'customer' === $( this ).val();
1406 if ( label ) {
1407 $( '#woocommerce-order-notes button.add_note' ).text( label );
1408 }
1409 $( '#woocommerce-order-notes .add_note_email_settings' ).prop( 'hidden', ! isCustomer );
1410 },
1411
1412 add_order_note: function() {
1413 if ( ! $( 'textarea#add_order_note' ).val() ) {
1414 return;
1415 }
1416
1417 $( '#woocommerce-order-notes' ).block({
1418 message: null,
1419 overlayCSS: {
1420 background: '#fff',
1421 opacity: 0.6
1422 }
1423 });
1424
1425 var data = {
1426 action: 'woocommerce_add_order_note',
1427 post_id: woocommerce_admin_meta_boxes.post_id,
1428 note: $( 'textarea#add_order_note' ).val(),
1429 note_type: $( 'select#order_note_type' ).val(),
1430 security: woocommerce_admin_meta_boxes.add_order_note_nonce
1431 };
1432
1433 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
1434 $( 'ul.order_notes .no-items' ).remove();
1435 $( 'ul.order_notes' ).prepend( response );
1436 $( '#woocommerce-order-notes' ).unblock();
1437 $( '#add_order_note' ).val( '' );
1438
1439 // Announce the result to screen readers (WCAG 4.1.3).
1440 if ( window.wp && window.wp.a11y && 'function' === typeof window.wp.a11y.speak ) {
1441 var message = 'customer' === data.note_type
1442 ? woocommerce_admin_meta_boxes.i18n_customer_order_note_added
1443 : woocommerce_admin_meta_boxes.i18n_order_note_added;
1444 if ( message ) {
1445 window.wp.a11y.speak( message, 'polite' );
1446 }
1447 }
1448
1449 window.wcTracks.recordEvent( 'order_edit_add_order_note', {
1450 order_id: woocommerce_admin_meta_boxes.post_id,
1451 note_type: data.note_type || 'private',
1452 status: $( '#order_status' ).val()
1453 } );
1454 });
1455
1456 return false;
1457 },
1458
1459 delete_order_note: function() {
1460 var note = $( this ).closest( 'li.note' );
1461 var message = note.hasClass( 'customer-note' )
1462 ? woocommerce_admin_meta_boxes.i18n_delete_customer_note
1463 : woocommerce_admin_meta_boxes.i18n_delete_note;
1464
1465 if ( window.confirm( message ) ) {
1466
1467 $( note ).block({
1468 message: null,
1469 overlayCSS: {
1470 background: '#fff',
1471 opacity: 0.6
1472 }
1473 });
1474
1475 var data = {
1476 action: 'woocommerce_delete_order_note',
1477 note_id: $( note ).attr( 'rel' ),
1478 security: woocommerce_admin_meta_boxes.delete_order_note_nonce
1479 };
1480
1481 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function() {
1482 if ( window.wcTracks && window.wcTracks.recordEvent ) {
1483 var noteType = note.hasClass( 'customer-note' ) ? 'customer' : 'private';
1484 var dateStr = note.find( '.exact-date' ).attr( 'title' );
1485 var addedAt = dateStr ? new Date( dateStr.replace( ' ', 'T' ) ) : null;
1486 var seconds = ( addedAt && ! isNaN( addedAt.valueOf() ) )
1487 ? Math.round( ( Date.now() - addedAt.getTime() ) / 1000 )
1488 : null;
1489 window.wcTracks.recordEvent( 'order_edit_delete_order_note', {
1490 order_id: woocommerce_admin_meta_boxes.post_id,
1491 note_type: noteType,
1492 status: $( '#order_status' ).val(),
1493 seconds_since_added: seconds
1494 } );
1495 }
1496 $( note ).remove();
1497 var $list = $( 'ul.order_notes' );
1498 if ( 0 === $list.find( 'li.note' ).length ) {
1499 $list.append( $( '<li class="no-items"></li>' ).text( woocommerce_admin_meta_boxes.i18n_no_notes_yet ) );
1500 }
1501 });
1502 }
1503
1504 return false;
1505 }
1506 };
1507
1508 /**
1509 * Order Downloads Panel
1510 */
1511 var wc_meta_boxes_order_downloads = {
1512 init: function() {
1513 $( '.order_download_permissions' )
1514 .on( 'click', 'button.grant_access', this.grant_access )
1515 .on( 'click', 'button.revoke_access', this.revoke_access )
1516 .on( 'click', '#copy-download-link', this.copy_link )
1517 .on( 'aftercopy', '#copy-download-link', this.copy_success )
1518 .on( 'aftercopyfailure', '#copy-download-link', this.copy_fail );
1519
1520 // Work around WP's callback for '.handlediv' hiding the containing WP metabox instead of just the WC one.
1521 $( '.order_download_permissions .wc-metabox .handlediv' ).on( 'click', function( e ) {
1522 e.stopImmediatePropagation();
1523 $( this ).closest( 'h3' ).trigger( 'click' );
1524 } );
1525 },
1526
1527 grant_access: function() {
1528 var products = $( '#grant_access_id' ).val();
1529
1530 if ( ! products || 0 === products.length ) {
1531 return;
1532 }
1533
1534 $( '.order_download_permissions' ).block({
1535 message: null,
1536 overlayCSS: {
1537 background: '#fff',
1538 opacity: 0.6
1539 }
1540 });
1541
1542 var data = {
1543 action: 'woocommerce_grant_access_to_download',
1544 product_ids: products,
1545 loop: $('.order_download_permissions .wc-metabox').length,
1546 order_id: woocommerce_admin_meta_boxes.post_id,
1547 security: woocommerce_admin_meta_boxes.grant_access_nonce
1548 };
1549
1550 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
1551 if ( response && -1 !== parseInt( response ) ) {
1552 var existingDownloads = {};
1553 var $newPermissions = $( response ).filter( '.wc-metabox' );
1554
1555 $( '.order_download_permissions .revoke_access' ).each( function() {
1556 existingDownloads[ $( this ).attr( 'rel' ) ] = true;
1557 } );
1558
1559 $newPermissions = $newPermissions.filter( function() {
1560 var downloadKey = $( this ).find( '.revoke_access' ).attr( 'rel' );
1561
1562 if ( existingDownloads[ downloadKey ] ) {
1563 return false;
1564 }
1565
1566 existingDownloads[ downloadKey ] = true;
1567 return true;
1568 } );
1569
1570 $( '.order_download_permissions .wc-metaboxes' ).append( $newPermissions );
1571 } else {
1572 window.alert( woocommerce_admin_meta_boxes.i18n_download_permission_fail );
1573 }
1574
1575 $( document.body ).trigger( 'wc-init-datepickers' );
1576 $( '#grant_access_id' ).val( '' ).trigger( 'change' );
1577 $( '.order_download_permissions' ).unblock();
1578 });
1579
1580 return false;
1581 },
1582
1583 revoke_access: function () {
1584 if ( window.confirm( woocommerce_admin_meta_boxes.i18n_permission_revoke ) ) {
1585 var el = $( this ).parent().parent();
1586 var product = $( this ).attr( 'rel' ).split( ',' )[0];
1587 var file = $( this ).attr( 'rel' ).split( ',' )[1];
1588 var permission_id = $( this ).data( 'permission_id' );
1589
1590 if ( product > 0 ) {
1591 $( el ).block({
1592 message: null,
1593 overlayCSS: {
1594 background: '#fff',
1595 opacity: 0.6
1596 }
1597 });
1598
1599 var data = {
1600 action: 'woocommerce_revoke_access_to_download',
1601 product_id: product,
1602 download_id: file,
1603 permission_id: permission_id,
1604 order_id: woocommerce_admin_meta_boxes.post_id,
1605 security: woocommerce_admin_meta_boxes.revoke_access_nonce
1606 };
1607
1608 $.post( woocommerce_admin_meta_boxes.ajax_url, data, function() {
1609 // Success
1610 $( el ).fadeOut( '300', function () {
1611 $( el ).remove();
1612 });
1613 });
1614
1615 } else {
1616 $( el ).fadeOut( '300', function () {
1617 $( el ).remove();
1618 });
1619 }
1620 }
1621 return false;
1622 },
1623
1624 /**
1625 * Copy download link.
1626 *
1627 * @param {Object} evt Copy event.
1628 */
1629 copy_link: function( evt ) {
1630 wcClearClipboard();
1631 wcSetClipboard( $( this ).attr( 'href' ), $( this ) );
1632 evt.preventDefault();
1633 },
1634
1635 /**
1636 * Display a "Copied!" tip when success copying
1637 */
1638 copy_success: function() {
1639 $( this ).tipTip({
1640 'attribute': 'data-tip',
1641 'activation': 'focus',
1642 'fadeIn': 50,
1643 'fadeOut': 50,
1644 'delay': 0
1645 }).trigger( 'focus' );
1646 },
1647
1648 /**
1649 * Displays the copy error message when failure copying.
1650 */
1651 copy_fail: function() {
1652 $( this ).tipTip({
1653 'attribute': 'data-tip-failed',
1654 'activation': 'focus',
1655 'fadeIn': 50,
1656 'fadeOut': 50,
1657 'delay': 0
1658 }).trigger( 'focus' );
1659 }
1660 };
1661
1662 /**
1663 * Configures ajax request for custom metadata box in order edit screen.
1664 */
1665 var wc_meta_boxes_order_custom_meta = {
1666 init: function() {
1667 let select2_args;
1668 let metakey_select;
1669
1670 if ( ! $('#order_custom').length ) {
1671 return;
1672 }
1673
1674 $( '#order_custom #the-list' ).wpList( {
1675 /**
1676 * Add order id and action to the request.
1677 */
1678 addBefore: function( settings ) {
1679 settings.data += "&order_id=" + woocommerce_admin_meta_boxes.post_id + "&action=woocommerce_order_add_meta";
1680 return settings;
1681 },
1682
1683 addAfter: function() {
1684 $('table#list-table').show();
1685 },
1686
1687 delBefore: function( settings, el ) {
1688 if (typeof select2_args.ajax == 'undefined') {
1689 // If the list of meta keys have already loaded, prepend the deleted key to the list if it isn't already present.
1690 let meta_key = $(el).find('#meta-' + settings.data.id + '-key').val();
1691 if (metakey_select.find('option[value=\'' + meta_key + '\']').length === 0) {
1692 let newOption = new Option(meta_key, meta_key, false, false);
1693 metakey_select.prepend(newOption);
1694 }
1695 }
1696 settings.data.order_id = woocommerce_admin_meta_boxes.post_id;
1697 settings.data.action = 'woocommerce_order_delete_meta';
1698 return settings;
1699 },
1700
1701 });
1702
1703 $( '#order_custom #metakeyselect').filter( function() {
1704 metakey_select = $(this);
1705 if(metakey_select.hasClass('enhanced)')) {
1706 return;
1707 }
1708
1709 select2_args = {
1710 allowClear: !!metakey_select.data('allow_clear'),
1711 placeholder: metakey_select.data('placeholder'),
1712 ajax: {
1713 url: wc_enhanced_select_params.ajax_url,
1714 dataType: 'json',
1715 delay: 500,
1716 data: function (params) {
1717 return {
1718 order_id: metakey_select.data('order_id'),
1719 action: 'woocommerce_json_search_order_metakeys',
1720 security: wc_enhanced_select_params.search_order_metakeys_nonce
1721 };
1722 },
1723 success: function (data) {
1724 let terms = [];
1725 if (data) {
1726 $.each(data, function (id, term) {
1727 terms.push({
1728 id: term,
1729 text: term,
1730 });
1731 });
1732 }
1733 // Reinitialize with the loaded data to avoid continued ajax requests when searching since
1734 // we are not using the search term to filter the list on the backend.
1735 select2_args.data = terms;
1736 delete select2_args.ajax;
1737 metakey_select.selectWoo(select2_args).select2('open');
1738 return false;
1739 },
1740 cache: true
1741 },
1742 language: {
1743 errorLoading: function () {
1744 // Workaround for https://github.com/select2/select2/issues/4355 instead of i18n_ajax_error.
1745 return wc_enhanced_select_params.i18n_searching;
1746 },
1747 inputTooLong: function (args) {
1748 var overChars = args.input.length - args.maximum;
1749
1750 if (1 === overChars) {
1751 return wc_enhanced_select_params.i18n_input_too_long_1;
1752 }
1753
1754 return wc_enhanced_select_params.i18n_input_too_long_n.replace('%qty%', overChars);
1755 },
1756 inputTooShort: function (args) {
1757 var remainingChars = args.minimum - args.input.length;
1758
1759 if (1 === remainingChars) {
1760 return wc_enhanced_select_params.i18n_input_too_short_1;
1761 }
1762
1763 return wc_enhanced_select_params.i18n_input_too_short_n.replace('%qty%', remainingChars);
1764 },
1765 loadingMore: function () {
1766 return wc_enhanced_select_params.i18n_load_more;
1767 },
1768 maximumSelected: function (args) {
1769 if (args.maximum === 1) {
1770 return wc_enhanced_select_params.i18n_selection_too_long_1;
1771 }
1772
1773 return wc_enhanced_select_params.i18n_selection_too_long_n.replace('%qty%', args.maximum);
1774 },
1775 noResults: function () {
1776 return wc_enhanced_select_params.i18n_no_matches;
1777 },
1778 searching: function () {
1779 return wc_enhanced_select_params.i18n_searching;
1780 }
1781 }
1782
1783 };
1784
1785 // Work around to deal with the lack of responsive support from Select2 until a better replacement can be integrated.
1786 let resizeTimer;
1787 $( window ).on( 'resize', function () {
1788 cancelAnimationFrame( resizeTimer );
1789 resizeTimer = requestAnimationFrame( function () {
1790 metakey_select.selectWoo( select2_args );
1791 } );
1792 });
1793
1794 metakey_select.selectWoo(select2_args).addClass('enhanced');
1795 });
1796 }
1797 };
1798
1799 wc_meta_boxes_order.init();
1800 wc_meta_boxes_order_items.init();
1801 wc_meta_boxes_order_notes.init();
1802 wc_meta_boxes_order_downloads.init();
1803 wc_meta_boxes_order_custom_meta.init();
1804
1805 /**
1806 * Event listeners to allow third-party plugins to reinitialize WooCommerce order meta boxes
1807 * after dynamically modifying their content.
1808 *
1809 * Usage Example:
1810 *
1811 * // Reinitialize the Order Data Panel:
1812 * window.dispatchEvent(new CustomEvent("wc_meta_boxes_order_init"));
1813 *
1814 * // Reinitialize Order Items Panel:
1815 * window.dispatchEvent(new CustomEvent("wc_meta_boxes_order_items_init"));
1816 *
1817 * These events ensure that order meta boxes can be dynamically updated
1818 * and properly reinitialized as needed.
1819 */
1820 window.addEventListener('wc_meta_boxes_order_init', (e) => {
1821 wc_meta_boxes_order.init()
1822 });
1823 window.addEventListener('wc_meta_boxes_order_items_init', (e) => {
1824 wc_meta_boxes_order_items.init()
1825 });
1826 window.addEventListener('wc_meta_boxes_order_notes_init', (e) => {
1827 wc_meta_boxes_order_notes.init()
1828 });
1829 window.addEventListener('wc_meta_boxes_order_downloads_init', (e) => {
1830 wc_meta_boxes_order_downloads.init()
1831 });
1832 window.addEventListener('wc_meta_boxes_order_custom_meta_init', (e) => {
1833 wc_meta_boxes_order_custom_meta.init()
1834 });
1835 });
1836