meta-boxes-product.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. /*global woocommerce_admin_meta_boxes */
  2. jQuery( function( $ ) {
  3. // Scroll to first checked category - https://github.com/scribu/wp-category-checklist-tree/blob/d1c3c1f449e1144542efa17dde84a9f52ade1739/category-checklist-tree.php
  4. $( function() {
  5. $( '[id$="-all"] > ul.categorychecklist' ).each( function() {
  6. var $list = $( this );
  7. var $firstChecked = $list.find( ':checked' ).first();
  8. if ( ! $firstChecked.length ) {
  9. return;
  10. }
  11. var pos_first = $list.find( 'input' ).position().top;
  12. var pos_checked = $firstChecked.position().top;
  13. $list.closest( '.tabs-panel' ).scrollTop( pos_checked - pos_first + 5 );
  14. });
  15. });
  16. // Prevent enter submitting post form.
  17. $( '#upsell_product_data' ).bind( 'keypress', function( e ) {
  18. if ( e.keyCode === 13 ) {
  19. return false;
  20. }
  21. });
  22. // Type box.
  23. $( '.type_box' ).appendTo( '#woocommerce-product-data .hndle span' );
  24. $( function() {
  25. // Prevent inputs in meta box headings opening/closing contents.
  26. $( '#woocommerce-product-data' ).find( '.hndle' ).unbind( 'click.postboxes' );
  27. $( '#woocommerce-product-data' ).on( 'click', '.hndle', function( event ) {
  28. // If the user clicks on some form input inside the h3 the box should not be toggled.
  29. if ( $( event.target ).filter( 'input, option, label, select' ).length ) {
  30. return;
  31. }
  32. $( '#woocommerce-product-data' ).toggleClass( 'closed' );
  33. });
  34. });
  35. // Catalog Visibility.
  36. $( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).click( function() {
  37. if ( $( '#catalog-visibility-select' ).is( ':hidden' ) ) {
  38. $( '#catalog-visibility-select' ).slideDown( 'fast' );
  39. $( this ).hide();
  40. }
  41. return false;
  42. });
  43. $( '#catalog-visibility' ).find( '.save-post-visibility' ).click( function() {
  44. $( '#catalog-visibility-select' ).slideUp( 'fast' );
  45. $( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).show();
  46. var label = $( 'input[name=_visibility]:checked' ).attr( 'data-label' );
  47. if ( $( 'input[name=_featured]' ).is( ':checked' ) ) {
  48. label = label + ', ' + woocommerce_admin_meta_boxes.featured_label;
  49. $( 'input[name=_featured]' ).attr( 'checked', 'checked' );
  50. }
  51. $( '#catalog-visibility-display' ).text( label );
  52. return false;
  53. });
  54. $( '#catalog-visibility' ).find( '.cancel-post-visibility' ).click( function() {
  55. $( '#catalog-visibility-select' ).slideUp( 'fast' );
  56. $( '#catalog-visibility' ).find( '.edit-catalog-visibility' ).show();
  57. var current_visibility = $( '#current_visibility' ).val();
  58. var current_featured = $( '#current_featured' ).val();
  59. $( 'input[name=_visibility]' ).removeAttr( 'checked' );
  60. $( 'input[name=_visibility][value=' + current_visibility + ']' ).attr( 'checked', 'checked' );
  61. var label = $( 'input[name=_visibility]:checked' ).attr( 'data-label' );
  62. if ( 'yes' === current_featured ) {
  63. label = label + ', ' + woocommerce_admin_meta_boxes.featured_label;
  64. $( 'input[name=_featured]' ).attr( 'checked', 'checked' );
  65. } else {
  66. $( 'input[name=_featured]' ).removeAttr( 'checked' );
  67. }
  68. $( '#catalog-visibility-display' ).text( label );
  69. return false;
  70. });
  71. // Product type specific options.
  72. $( 'select#product-type' ).change( function() {
  73. // Get value.
  74. var select_val = $( this ).val();
  75. if ( 'variable' === select_val ) {
  76. $( 'input#_manage_stock' ).change();
  77. $( 'input#_downloadable' ).prop( 'checked', false );
  78. $( 'input#_virtual' ).removeAttr( 'checked' );
  79. } else if ( 'grouped' === select_val ) {
  80. $( 'input#_downloadable' ).prop( 'checked', false );
  81. $( 'input#_virtual' ).removeAttr( 'checked' );
  82. } else if ( 'external' === select_val ) {
  83. $( 'input#_downloadable' ).prop( 'checked', false );
  84. $( 'input#_virtual' ).removeAttr( 'checked' );
  85. }
  86. show_and_hide_panels();
  87. $( 'ul.wc-tabs li:visible' ).eq( 0 ).find( 'a' ).click();
  88. $( document.body ).trigger( 'woocommerce-product-type-change', select_val, $( this ) );
  89. }).change();
  90. $( 'input#_downloadable, input#_virtual' ).change( function() {
  91. show_and_hide_panels();
  92. });
  93. function show_and_hide_panels() {
  94. var product_type = $( 'select#product-type' ).val();
  95. var is_virtual = $( 'input#_virtual:checked' ).length;
  96. var is_downloadable = $( 'input#_downloadable:checked' ).length;
  97. // Hide/Show all with rules.
  98. var hide_classes = '.hide_if_downloadable, .hide_if_virtual';
  99. var show_classes = '.show_if_downloadable, .show_if_virtual';
  100. $.each( woocommerce_admin_meta_boxes.product_types, function( index, value ) {
  101. hide_classes = hide_classes + ', .hide_if_' + value;
  102. show_classes = show_classes + ', .show_if_' + value;
  103. });
  104. $( hide_classes ).show();
  105. $( show_classes ).hide();
  106. // Shows rules.
  107. if ( is_downloadable ) {
  108. $( '.show_if_downloadable' ).show();
  109. }
  110. if ( is_virtual ) {
  111. $( '.show_if_virtual' ).show();
  112. }
  113. $( '.show_if_' + product_type ).show();
  114. // Hide rules.
  115. if ( is_downloadable ) {
  116. $( '.hide_if_downloadable' ).hide();
  117. }
  118. if ( is_virtual ) {
  119. $( '.hide_if_virtual' ).hide();
  120. }
  121. $( '.hide_if_' + product_type ).hide();
  122. $( 'input#_manage_stock' ).change();
  123. // Hide empty panels/tabs after display.
  124. $( '.woocommerce_options_panel' ).each( function() {
  125. var $children = $( this ).children( '.options_group' );
  126. if ( 0 === $children.length ) {
  127. return;
  128. }
  129. var $invisble = $children.filter( function() {
  130. return 'none' === $( this ).css( 'display' );
  131. });
  132. // Hide panel.
  133. if ( $invisble.length === $children.length ) {
  134. var $id = $( this ).prop( 'id' );
  135. $( '.product_data_tabs' ).find( 'li a[href="#' + $id + '"]' ).parent().hide();
  136. }
  137. });
  138. }
  139. // Sale price schedule.
  140. $( '.sale_price_dates_fields' ).each( function() {
  141. var $these_sale_dates = $( this );
  142. var sale_schedule_set = false;
  143. var $wrap = $these_sale_dates.closest( 'div, table' );
  144. $these_sale_dates.find( 'input' ).each( function() {
  145. if ( '' !== $( this ).val() ) {
  146. sale_schedule_set = true;
  147. }
  148. });
  149. if ( sale_schedule_set ) {
  150. $wrap.find( '.sale_schedule' ).hide();
  151. $wrap.find( '.sale_price_dates_fields' ).show();
  152. } else {
  153. $wrap.find( '.sale_schedule' ).show();
  154. $wrap.find( '.sale_price_dates_fields' ).hide();
  155. }
  156. });
  157. $( '#woocommerce-product-data' ).on( 'click', '.sale_schedule', function() {
  158. var $wrap = $( this ).closest( 'div, table' );
  159. $( this ).hide();
  160. $wrap.find( '.cancel_sale_schedule' ).show();
  161. $wrap.find( '.sale_price_dates_fields' ).show();
  162. return false;
  163. });
  164. $( '#woocommerce-product-data' ).on( 'click', '.cancel_sale_schedule', function() {
  165. var $wrap = $( this ).closest( 'div, table' );
  166. $( this ).hide();
  167. $wrap.find( '.sale_schedule' ).show();
  168. $wrap.find( '.sale_price_dates_fields' ).hide();
  169. $wrap.find( '.sale_price_dates_fields' ).find( 'input' ).val('');
  170. return false;
  171. });
  172. // File inputs.
  173. $( '#woocommerce-product-data' ).on( 'click','.downloadable_files a.insert', function() {
  174. $( this ).closest( '.downloadable_files' ).find( 'tbody' ).append( $( this ).data( 'row' ) );
  175. return false;
  176. });
  177. $( '#woocommerce-product-data' ).on( 'click','.downloadable_files a.delete',function() {
  178. $( this ).closest( 'tr' ).remove();
  179. return false;
  180. });
  181. // Stock options.
  182. $( 'input#_manage_stock' ).change( function() {
  183. if ( $( this ).is( ':checked' ) ) {
  184. $( 'div.stock_fields' ).show();
  185. $( 'p.stock_status_field' ).hide();
  186. } else {
  187. var product_type = $( 'select#product-type' ).val();
  188. $( 'div.stock_fields' ).hide();
  189. $( 'p.stock_status_field:not( .hide_if_' + product_type + ' )' ).show();
  190. }
  191. }).change();
  192. // Date picker fields.
  193. function date_picker_select( datepicker ) {
  194. var option = $( datepicker ).next().is( '.hasDatepicker' ) ? 'minDate' : 'maxDate',
  195. otherDateField = 'minDate' === option ? $( datepicker ).next() : $( datepicker ).prev(),
  196. date = $( datepicker ).datepicker( 'getDate' );
  197. $( otherDateField ).datepicker( 'option', option, date );
  198. $( datepicker ).change();
  199. }
  200. $( '.sale_price_dates_fields' ).each( function() {
  201. $( this ).find( 'input' ).datepicker({
  202. defaultDate: '',
  203. dateFormat: 'yy-mm-dd',
  204. numberOfMonths: 1,
  205. showButtonPanel: true,
  206. onSelect: function() {
  207. date_picker_select( $( this ) );
  208. }
  209. });
  210. $( this ).find( 'input' ).each( function() { date_picker_select( $( this ) ); } );
  211. });
  212. // Attribute Tables.
  213. // Initial order.
  214. var woocommerce_attribute_items = $( '.product_attributes' ).find( '.woocommerce_attribute' ).get();
  215. woocommerce_attribute_items.sort( function( a, b ) {
  216. var compA = parseInt( $( a ).attr( 'rel' ), 10 );
  217. var compB = parseInt( $( b ).attr( 'rel' ), 10 );
  218. return ( compA < compB ) ? -1 : ( compA > compB ) ? 1 : 0;
  219. });
  220. $( woocommerce_attribute_items ).each( function( index, el ) {
  221. $( '.product_attributes' ).append( el );
  222. });
  223. function attribute_row_indexes() {
  224. $( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
  225. $( '.attribute_position', el ).val( parseInt( $( el ).index( '.product_attributes .woocommerce_attribute' ), 10 ) );
  226. });
  227. }
  228. $( '.product_attributes .woocommerce_attribute' ).each( function( index, el ) {
  229. if ( $( el ).css( 'display' ) !== 'none' && $( el ).is( '.taxonomy' ) ) {
  230. $( 'select.attribute_taxonomy' ).find( 'option[value="' + $( el ).data( 'taxonomy' ) + '"]' ).attr( 'disabled', 'disabled' );
  231. }
  232. });
  233. // Add rows.
  234. $( 'button.add_attribute' ).on( 'click', function() {
  235. var size = $( '.product_attributes .woocommerce_attribute' ).length;
  236. var attribute = $( 'select.attribute_taxonomy' ).val();
  237. var $wrapper = $( this ).closest( '#product_attributes' );
  238. var $attributes = $wrapper.find( '.product_attributes' );
  239. var product_type = $( 'select#product-type' ).val();
  240. var data = {
  241. action: 'woocommerce_add_attribute',
  242. taxonomy: attribute,
  243. i: size,
  244. security: woocommerce_admin_meta_boxes.add_attribute_nonce
  245. };
  246. $wrapper.block({
  247. message: null,
  248. overlayCSS: {
  249. background: '#fff',
  250. opacity: 0.6
  251. }
  252. });
  253. $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
  254. $attributes.append( response );
  255. if ( 'variable' !== product_type ) {
  256. $attributes.find( '.enable_variation' ).hide();
  257. }
  258. $( document.body ).trigger( 'wc-enhanced-select-init' );
  259. attribute_row_indexes();
  260. $wrapper.unblock();
  261. $( document.body ).trigger( 'woocommerce_added_attribute' );
  262. });
  263. if ( attribute ) {
  264. $( 'select.attribute_taxonomy' ).find( 'option[value="' + attribute + '"]' ).attr( 'disabled','disabled' );
  265. $( 'select.attribute_taxonomy' ).val( '' );
  266. }
  267. return false;
  268. });
  269. $( '.product_attributes' ).on( 'blur', 'input.attribute_name', function() {
  270. $( this ).closest( '.woocommerce_attribute' ).find( 'strong.attribute_name' ).text( $( this ).val() );
  271. });
  272. $( '.product_attributes' ).on( 'click', 'button.select_all_attributes', function() {
  273. $( this ).closest( 'td' ).find( 'select option' ).attr( 'selected', 'selected' );
  274. $( this ).closest( 'td' ).find( 'select' ).change();
  275. return false;
  276. });
  277. $( '.product_attributes' ).on( 'click', 'button.select_no_attributes', function() {
  278. $( this ).closest( 'td' ).find( 'select option' ).removeAttr( 'selected' );
  279. $( this ).closest( 'td' ).find( 'select' ).change();
  280. return false;
  281. });
  282. $( '.product_attributes' ).on( 'click', '.remove_row', function() {
  283. if ( window.confirm( woocommerce_admin_meta_boxes.remove_attribute ) ) {
  284. var $parent = $( this ).parent().parent();
  285. if ( $parent.is( '.taxonomy' ) ) {
  286. $parent.find( 'select, input[type=text]' ).val( '' );
  287. $parent.hide();
  288. $( 'select.attribute_taxonomy' ).find( 'option[value="' + $parent.data( 'taxonomy' ) + '"]' ).removeAttr( 'disabled' );
  289. } else {
  290. $parent.find( 'select, input[type=text]' ).val( '' );
  291. $parent.hide();
  292. attribute_row_indexes();
  293. }
  294. }
  295. return false;
  296. });
  297. // Attribute ordering.
  298. $( '.product_attributes' ).sortable({
  299. items: '.woocommerce_attribute',
  300. cursor: 'move',
  301. axis: 'y',
  302. handle: 'h3',
  303. scrollSensitivity: 40,
  304. forcePlaceholderSize: true,
  305. helper: 'clone',
  306. opacity: 0.65,
  307. placeholder: 'wc-metabox-sortable-placeholder',
  308. start: function( event, ui ) {
  309. ui.item.css( 'background-color', '#f6f6f6' );
  310. },
  311. stop: function( event, ui ) {
  312. ui.item.removeAttr( 'style' );
  313. attribute_row_indexes();
  314. }
  315. });
  316. // Add a new attribute (via ajax).
  317. $( '.product_attributes' ).on( 'click', 'button.add_new_attribute', function() {
  318. $( '.product_attributes' ).block({
  319. message: null,
  320. overlayCSS: {
  321. background: '#fff',
  322. opacity: 0.6
  323. }
  324. });
  325. var $wrapper = $( this ).closest( '.woocommerce_attribute' );
  326. var attribute = $wrapper.data( 'taxonomy' );
  327. var new_attribute_name = window.prompt( woocommerce_admin_meta_boxes.new_attribute_prompt );
  328. if ( new_attribute_name ) {
  329. var data = {
  330. action: 'woocommerce_add_new_attribute',
  331. taxonomy: attribute,
  332. term: new_attribute_name,
  333. security: woocommerce_admin_meta_boxes.add_attribute_nonce
  334. };
  335. $.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
  336. if ( response.error ) {
  337. // Error.
  338. window.alert( response.error );
  339. } else if ( response.slug ) {
  340. // Success.
  341. $wrapper.find( 'select.attribute_values' ).append( '<option value="' + response.term_id + '" selected="selected">' + response.name + '</option>' );
  342. $wrapper.find( 'select.attribute_values' ).change();
  343. }
  344. $( '.product_attributes' ).unblock();
  345. });
  346. } else {
  347. $( '.product_attributes' ).unblock();
  348. }
  349. return false;
  350. });
  351. // Save attributes and update variations.
  352. $( '.save_attributes' ).on( 'click', function() {
  353. $( '#woocommerce-product-data' ).block({
  354. message: null,
  355. overlayCSS: {
  356. background: '#fff',
  357. opacity: 0.6
  358. }
  359. });
  360. var data = {
  361. post_id : woocommerce_admin_meta_boxes.post_id,
  362. product_type: $( '#product-type' ).val(),
  363. data : $( '.product_attributes' ).find( 'input, select, textarea' ).serialize(),
  364. action : 'woocommerce_save_attributes',
  365. security : woocommerce_admin_meta_boxes.save_attributes_nonce
  366. };
  367. $.post( woocommerce_admin_meta_boxes.ajax_url, data, function() {
  368. // Reload variations panel.
  369. var this_page = window.location.toString();
  370. this_page = this_page.replace( 'post-new.php?', 'post.php?post=' + woocommerce_admin_meta_boxes.post_id + '&action=edit&' );
  371. // Load variations panel.
  372. $( '#variable_product_options' ).load( this_page + ' #variable_product_options_inner', function() {
  373. $( '#variable_product_options' ).trigger( 'reload' );
  374. });
  375. });
  376. });
  377. // Uploading files.
  378. var downloadable_file_frame;
  379. var file_path_field;
  380. $( document.body ).on( 'click', '.upload_file_button', function( event ) {
  381. var $el = $( this );
  382. file_path_field = $el.closest( 'tr' ).find( 'td.file_url input' );
  383. event.preventDefault();
  384. // If the media frame already exists, reopen it.
  385. if ( downloadable_file_frame ) {
  386. downloadable_file_frame.open();
  387. return;
  388. }
  389. var downloadable_file_states = [
  390. // Main states.
  391. new wp.media.controller.Library({
  392. library: wp.media.query(),
  393. multiple: true,
  394. title: $el.data('choose'),
  395. priority: 20,
  396. filterable: 'uploaded'
  397. })
  398. ];
  399. // Create the media frame.
  400. downloadable_file_frame = wp.media.frames.downloadable_file = wp.media({
  401. // Set the title of the modal.
  402. title: $el.data('choose'),
  403. library: {
  404. type: ''
  405. },
  406. button: {
  407. text: $el.data('update')
  408. },
  409. multiple: true,
  410. states: downloadable_file_states
  411. });
  412. // When an image is selected, run a callback.
  413. downloadable_file_frame.on( 'select', function() {
  414. var file_path = '';
  415. var selection = downloadable_file_frame.state().get( 'selection' );
  416. selection.map( function( attachment ) {
  417. attachment = attachment.toJSON();
  418. if ( attachment.url ) {
  419. file_path = attachment.url;
  420. }
  421. });
  422. file_path_field.val( file_path ).change();
  423. });
  424. // Set post to 0 and set our custom type.
  425. downloadable_file_frame.on( 'ready', function() {
  426. downloadable_file_frame.uploader.options.uploader.params = {
  427. type: 'downloadable_product'
  428. };
  429. });
  430. // Finally, open the modal.
  431. downloadable_file_frame.open();
  432. });
  433. // Download ordering.
  434. $( '.downloadable_files tbody' ).sortable({
  435. items: 'tr',
  436. cursor: 'move',
  437. axis: 'y',
  438. handle: 'td.sort',
  439. scrollSensitivity: 40,
  440. forcePlaceholderSize: true,
  441. helper: 'clone',
  442. opacity: 0.65
  443. });
  444. // Product gallery file uploads.
  445. var product_gallery_frame;
  446. var $image_gallery_ids = $( '#product_image_gallery' );
  447. var $product_images = $( '#product_images_container' ).find( 'ul.product_images' );
  448. $( '.add_product_images' ).on( 'click', 'a', function( event ) {
  449. var $el = $( this );
  450. event.preventDefault();
  451. // If the media frame already exists, reopen it.
  452. if ( product_gallery_frame ) {
  453. product_gallery_frame.open();
  454. return;
  455. }
  456. // Create the media frame.
  457. product_gallery_frame = wp.media.frames.product_gallery = wp.media({
  458. // Set the title of the modal.
  459. title: $el.data( 'choose' ),
  460. button: {
  461. text: $el.data( 'update' )
  462. },
  463. states: [
  464. new wp.media.controller.Library({
  465. title: $el.data( 'choose' ),
  466. filterable: 'all',
  467. multiple: true
  468. })
  469. ]
  470. });
  471. // When an image is selected, run a callback.
  472. product_gallery_frame.on( 'select', function() {
  473. var selection = product_gallery_frame.state().get( 'selection' );
  474. var attachment_ids = $image_gallery_ids.val();
  475. selection.map( function( attachment ) {
  476. attachment = attachment.toJSON();
  477. if ( attachment.id ) {
  478. attachment_ids = attachment_ids ? attachment_ids + ',' + attachment.id : attachment.id;
  479. var attachment_image = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
  480. $product_images.append( '<li class="image" data-attachment_id="' + attachment.id + '"><img src="' + attachment_image + '" /><ul class="actions"><li><a href="#" class="delete" title="' + $el.data('delete') + '">' + $el.data('text') + '</a></li></ul></li>' );
  481. }
  482. });
  483. $image_gallery_ids.val( attachment_ids );
  484. });
  485. // Finally, open the modal.
  486. product_gallery_frame.open();
  487. });
  488. // Image ordering.
  489. $product_images.sortable({
  490. items: 'li.image',
  491. cursor: 'move',
  492. scrollSensitivity: 40,
  493. forcePlaceholderSize: true,
  494. forceHelperSize: false,
  495. helper: 'clone',
  496. opacity: 0.65,
  497. placeholder: 'wc-metabox-sortable-placeholder',
  498. start: function( event, ui ) {
  499. ui.item.css( 'background-color', '#f6f6f6' );
  500. },
  501. stop: function( event, ui ) {
  502. ui.item.removeAttr( 'style' );
  503. },
  504. update: function() {
  505. var attachment_ids = '';
  506. $( '#product_images_container' ).find( 'ul li.image' ).css( 'cursor', 'default' ).each( function() {
  507. var attachment_id = $( this ).attr( 'data-attachment_id' );
  508. attachment_ids = attachment_ids + attachment_id + ',';
  509. });
  510. $image_gallery_ids.val( attachment_ids );
  511. }
  512. });
  513. // Remove images.
  514. $( '#product_images_container' ).on( 'click', 'a.delete', function() {
  515. $( this ).closest( 'li.image' ).remove();
  516. var attachment_ids = '';
  517. $( '#product_images_container' ).find( 'ul li.image' ).css( 'cursor', 'default' ).each( function() {
  518. var attachment_id = $( this ).attr( 'data-attachment_id' );
  519. attachment_ids = attachment_ids + attachment_id + ',';
  520. });
  521. $image_gallery_ids.val( attachment_ids );
  522. // Remove any lingering tooltips.
  523. $( '#tiptip_holder' ).removeAttr( 'style' );
  524. $( '#tiptip_arrow' ).removeAttr( 'style' );
  525. return false;
  526. });
  527. });