PageRenderTime 254ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/assets/js/frontend/add-to-cart-variation.js

https://github.com/boxyman/woocommerce
JavaScript | 429 lines | 325 code | 82 blank | 22 comment | 45 complexity | 9668ebcac4d1b2d990c95ae623487af5 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0, BSD-3-Clause
  1. /*!
  2. * Variations Plugin
  3. */
  4. ;(function ( $, window, document, undefined ) {
  5. $.fn.wc_variation_form = function () {
  6. $.fn.wc_variation_form.find_matching_variations = function( product_variations, settings ) {
  7. var matching = [];
  8. for ( var i = 0; i < product_variations.length; i++ ) {
  9. var variation = product_variations[i];
  10. var variation_id = variation.variation_id;
  11. if ( $.fn.wc_variation_form.variations_match( variation.attributes, settings ) ) {
  12. matching.push( variation );
  13. }
  14. }
  15. return matching;
  16. };
  17. $.fn.wc_variation_form.variations_match = function( attrs1, attrs2 ) {
  18. var match = true;
  19. for ( var attr_name in attrs1 ) {
  20. if ( attrs1.hasOwnProperty( attr_name ) ) {
  21. var val1 = attrs1[ attr_name ];
  22. var val2 = attrs2[ attr_name ];
  23. if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
  24. match = false;
  25. }
  26. }
  27. }
  28. return match;
  29. };
  30. // Unbind any existing events
  31. this.unbind( 'check_variations update_variation_values found_variation' );
  32. this.find( '.reset_variations' ).unbind( 'click' );
  33. this.find( '.variations select' ).unbind( 'change focusin' );
  34. // Bind events
  35. $form = this
  36. // On clicking the reset variation button
  37. .on( 'click', '.reset_variations', function( event ) {
  38. $( this ).closest( '.variations_form' ).find( '.variations select' ).val( '' ).change();
  39. var $sku = $( this ).closest( '.product' ).find( '.sku' ),
  40. $weight = $( this ).closest( '.product' ).find( '.product_weight' ),
  41. $dimensions = $( this ).closest( '.product' ).find( '.product_dimensions' );
  42. if ( $sku.attr( 'data-o_sku' ) )
  43. $sku.text( $sku.attr( 'data-o_sku' ) );
  44. if ( $weight.attr( 'data-o_weight' ) )
  45. $weight.text( $weight.attr( 'data-o_weight' ) );
  46. if ( $dimensions.attr( 'data-o_dimensions' ) )
  47. $dimensions.text( $dimensions.attr( 'data-o_dimensions' ) );
  48. return false;
  49. } )
  50. // Upon changing an option
  51. .on( 'change', '.variations select', function( event ) {
  52. $variation_form = $( this ).closest( '.variations_form' );
  53. $variation_form.find( 'input[name=variation_id]' ).val( '' ).change();
  54. $variation_form
  55. .trigger( 'woocommerce_variation_select_change' )
  56. .trigger( 'check_variations', [ '', false ] );
  57. $( this ).blur();
  58. if( $().uniform && $.isFunction( $.uniform.update ) ) {
  59. $.uniform.update();
  60. }
  61. } )
  62. // Upon gaining focus
  63. .on( 'focusin touchstart', '.variations select', function( event ) {
  64. $variation_form = $( this ).closest( '.variations_form' );
  65. $variation_form
  66. .trigger( 'woocommerce_variation_select_focusin' )
  67. .trigger( 'check_variations', [ $( this ).attr( 'name' ), true ] );
  68. } )
  69. // Check variations
  70. .on( 'check_variations', function( event, exclude, focus ) {
  71. var all_set = true,
  72. any_set = false,
  73. showing_variation = false,
  74. current_settings = {},
  75. $variation_form = $( this ),
  76. $reset_variations = $variation_form.find( '.reset_variations' );
  77. $variation_form.find( '.variations select' ).each( function() {
  78. if ( $( this ).val().length === 0 ) {
  79. all_set = false;
  80. } else {
  81. any_set = true;
  82. }
  83. if ( exclude && $( this ).attr( 'name' ) === exclude ) {
  84. all_set = false;
  85. current_settings[$( this ).attr( 'name' )] = '';
  86. } else {
  87. // Encode entities
  88. value = $( this ).val();
  89. // Add to settings array
  90. current_settings[ $( this ).attr( 'name' ) ] = value;
  91. }
  92. });
  93. var product_id = parseInt( $variation_form.data( 'product_id' ) ),
  94. all_variations = $variation_form.data( 'product_variations' );
  95. // Fallback to window property if not set - backwards compat
  96. if ( ! all_variations )
  97. all_variations = window.product_variations.product_id;
  98. if ( ! all_variations )
  99. all_variations = window.product_variations;
  100. if ( ! all_variations )
  101. all_variations = window['product_variations_' + product_id ];
  102. var matching_variations = $.fn.wc_variation_form.find_matching_variations( all_variations, current_settings );
  103. if ( all_set ) {
  104. var variation = matching_variations.shift();
  105. if ( variation ) {
  106. // Found - set ID
  107. $variation_form
  108. .find( 'input[name=variation_id]' )
  109. .val( variation.variation_id )
  110. .change();
  111. $variation_form.trigger( 'found_variation', [ variation ] );
  112. } else {
  113. // Nothing found - reset fields
  114. $variation_form.find( '.variations select' ).val( '' );
  115. if ( ! focus )
  116. $variation_form.trigger( 'reset_image' );
  117. alert( wc_add_to_cart_variation_params.i18n_no_matching_variations_text );
  118. }
  119. } else {
  120. $variation_form.trigger( 'update_variation_values', [ matching_variations ] );
  121. if ( ! focus )
  122. $variation_form.trigger( 'reset_image' );
  123. if ( ! exclude ) {
  124. $variation_form.find( '.single_variation_wrap' ).slideUp( 200 );
  125. }
  126. }
  127. if ( any_set ) {
  128. if ( $reset_variations.css( 'visibility' ) === 'hidden' )
  129. $reset_variations.css( 'visibility', 'visible' ).hide().fadeIn();
  130. } else {
  131. $reset_variations.css( 'visibility', 'hidden' );
  132. }
  133. } )
  134. // Reset product image
  135. .on( 'reset_image', function( event ) {
  136. var $product = $(this).closest( '.product' ),
  137. $product_img = $product.find( 'div.images img:eq(0)' ),
  138. $product_link = $product.find( 'div.images a.zoom:eq(0)' ),
  139. o_src = $product_img.attr( 'data-o_src' ),
  140. o_title = $product_img.attr( 'data-o_title' ),
  141. o_alt = $product_img.attr( 'data-o_alt' ),
  142. o_href = $product_link.attr( 'data-o_href' );
  143. if ( o_src !== undefined ) {
  144. $product_img
  145. .attr( 'src', o_src );
  146. }
  147. if ( o_href !== undefined ) {
  148. $product_link
  149. .attr( 'href', o_href );
  150. }
  151. if ( o_title !== undefined ) {
  152. $product_img
  153. .attr( 'title', o_title );
  154. $product_link
  155. .attr( 'title', o_title );
  156. }
  157. if ( o_alt !== undefined ) {
  158. $product_img
  159. .attr( 'alt', o_alt );
  160. }
  161. } )
  162. // Disable option fields that are unavaiable for current set of attributes
  163. .on( 'update_variation_values', function( event, variations ) {
  164. $variation_form = $( this ).closest( '.variations_form' );
  165. // Loop through selects and disable/enable options based on selections
  166. $variation_form.find( '.variations select' ).each( function( index, el ) {
  167. current_attr_select = $( el );
  168. // Reset options
  169. if ( ! current_attr_select.data( 'attribute_options' ) )
  170. current_attr_select.data( 'attribute_options', current_attr_select.find( 'option:gt(0)' ).get() );
  171. current_attr_select.find( 'option:gt(0)' ).remove();
  172. current_attr_select.append( current_attr_select.data( 'attribute_options' ) );
  173. current_attr_select.find( 'option:gt(0)' ).removeClass( 'active' );
  174. // Get name
  175. var current_attr_name = current_attr_select.attr( 'name' );
  176. // Loop through variations
  177. for ( var num in variations ) {
  178. if ( typeof( variations[ num ] ) != 'undefined' ) {
  179. var attributes = variations[ num ].attributes;
  180. for ( var attr_name in attributes ) {
  181. if ( attributes.hasOwnProperty( attr_name ) ) {
  182. var attr_val = attributes[ attr_name ];
  183. if ( attr_name == current_attr_name ) {
  184. if ( attr_val ) {
  185. // Decode entities
  186. attr_val = $( '<div/>' ).html( attr_val ).text();
  187. // Add slashes
  188. attr_val = attr_val.replace( /'/g, "\\'" );
  189. attr_val = attr_val.replace( /"/g, "\\\"" );
  190. // Compare the meerkat
  191. current_attr_select.find( 'option[value="' + attr_val + '"]' ).addClass( 'active' );
  192. } else {
  193. current_attr_select.find( 'option:gt(0)' ).addClass( 'active' );
  194. }
  195. }
  196. }
  197. }
  198. }
  199. }
  200. // Detach inactive
  201. current_attr_select.find( 'option:gt(0):not(.active)' ).remove();
  202. });
  203. // Custom event for when variations have been updated
  204. $variation_form.trigger( 'woocommerce_update_variation_values' );
  205. } )
  206. // Show single variation details (price, stock, image)
  207. .on( 'found_variation', function( event, variation ) {
  208. var $variation_form = $( this ),
  209. $product = $( this ).closest( '.product' ),
  210. $product_img = $product.find( 'div.images img:eq(0)' ),
  211. $product_link = $product.find( 'div.images a.zoom:eq(0)' ),
  212. o_src = $product_img.attr( 'data-o_src' ),
  213. o_title = $product_img.attr( 'data-o_title' ),
  214. o_alt = $product_img.attr( 'data-o_alt' ),
  215. o_href = $product_link.attr( 'data-o_href' ),
  216. variation_image = variation.image_src,
  217. variation_link = variation.image_link,
  218. variation_title = variation.image_title,
  219. variation_alt = variation.image_alt;
  220. $variation_form.find( '.variations_button' ).show();
  221. $variation_form.find( '.single_variation' ).html( variation.price_html + variation.availability_html );
  222. if ( o_src === undefined ) {
  223. o_src = ( ! $product_img.attr( 'src' ) ) ? '' : $product_img.attr( 'src' );
  224. $product_img.attr( 'data-o_src', o_src );
  225. }
  226. if ( o_href === undefined ) {
  227. o_href = ( ! $product_link.attr( 'href' ) ) ? '' : $product_link.attr( 'href' );
  228. $product_link.attr( 'data-o_href', o_href );
  229. }
  230. if ( o_title === undefined ) {
  231. o_title = ( ! $product_img.attr( 'title' ) ) ? '' : $product_img.attr( 'title' );
  232. $product_img.attr( 'data-o_title', o_title );
  233. }
  234. if ( o_alt === undefined ) {
  235. o_alt = ( ! $product_img.attr( 'alt' ) ) ? '' : $product_img.attr( 'alt' );
  236. $product_img.attr( 'data-o_alt', o_alt );
  237. }
  238. if ( variation_image && variation_image.length > 1 ) {
  239. $product_img
  240. .attr( 'src', variation_image )
  241. .attr( 'alt', variation_alt )
  242. .attr( 'title', variation_title );
  243. $product_link
  244. .attr( 'href', variation_link )
  245. .attr( 'title', variation_title );
  246. } else {
  247. $product_img
  248. .attr( 'src', o_src )
  249. .attr( 'alt', o_alt )
  250. .attr( 'title', o_title );
  251. $product_link
  252. .attr( 'href', o_href )
  253. .attr( 'title', o_title );
  254. }
  255. var $single_variation_wrap = $variation_form.find( '.single_variation_wrap' ),
  256. $sku = $product.find( '.product_meta' ).find( '.sku' ),
  257. $weight = $product.find( '.product_weight' ),
  258. $dimensions = $product.find( '.product_dimensions' );
  259. if ( ! $sku.attr( 'data-o_sku' ) )
  260. $sku.attr( 'data-o_sku', $sku.text() );
  261. if ( ! $weight.attr( 'data-o_weight' ) )
  262. $weight.attr( 'data-o_weight', $weight.text() );
  263. if ( ! $dimensions.attr( 'data-o_dimensions' ) )
  264. $dimensions.attr( 'data-o_dimensions', $dimensions.text() );
  265. if ( variation.sku ) {
  266. $sku.text( variation.sku );
  267. } else {
  268. $sku.text( $sku.attr( 'data-o_sku' ) );
  269. }
  270. if ( variation.weight ) {
  271. $weight.text( variation.weight );
  272. } else {
  273. $weight.text( $weight.attr( 'data-o_weight' ) );
  274. }
  275. if ( variation.dimensions ) {
  276. $dimensions.text( variation.dimensions );
  277. } else {
  278. $dimensions.text( $dimensions.attr( 'data-o_dimensions' ) );
  279. }
  280. $single_variation_wrap.find( '.quantity' ).show();
  281. if ( ! variation.is_purchasable || ! variation.is_in_stock || ! variation.variation_is_visible ) {
  282. $variation_form.find( '.variations_button' ).hide();
  283. }
  284. if ( ! variation.variation_is_visible ) {
  285. $variation_form.find( '.single_variation' ).html( '<p>' + wc_add_to_cart_variation_params.i18n_unavailable_text + '</p>' );
  286. }
  287. if ( variation.min_qty )
  288. $single_variation_wrap.find( 'input[name=quantity]' ).attr( 'min', variation.min_qty ).val( variation.min_qty );
  289. else
  290. $single_variation_wrap.find( 'input[name=quantity]' ).removeAttr( 'min' );
  291. if ( variation.max_qty )
  292. $single_variation_wrap.find( 'input[name=quantity]' ).attr( 'max', variation.max_qty );
  293. else
  294. $single_variation_wrap.find( 'input[name=quantity]' ).removeAttr( 'max' );
  295. if ( variation.is_sold_individually === 'yes' ) {
  296. $single_variation_wrap.find( 'input[name=quantity]' ).val( '1' );
  297. $single_variation_wrap.find( '.quantity' ).hide();
  298. }
  299. $single_variation_wrap.slideDown( 200 ).trigger( 'show_variation', [ variation ] );
  300. });
  301. $form.trigger( 'wc_variation_form' );
  302. return $form;
  303. };
  304. $( function() {
  305. // wc_add_to_cart_variation_params is required to continue, ensure the object exists
  306. if ( typeof wc_add_to_cart_variation_params === 'undefined' )
  307. return false;
  308. $( '.variations_form' ).wc_variation_form();
  309. $( '.variations_form .variations select' ).change();
  310. });
  311. })( jQuery, window, document );