
	var blnRunSearch = true;

	function ajaxQuickOrderProductSearch(strKeyword, strAutocompleteID) {
		blnRunSearch = false;

		if (strKeyword.length > 1)
    {
			rowID = strAutocompleteID.replace(/product_reference_/, '');
			strProductID = '';
			strTitle = '';
			strPrice = '';
			strOptions = '';
			row = $('#quick_order_row' + rowID);
			row.find('td.quick_title span').html('').eq(0).html('Loading...');

			$.ajaxSetup({ scriptCharset: "utf-8" , contentType: "application/json; charset=utf-8"});
			$.getJSON(
				'/ajax/lookup_child_products/' + strKeyword,
				function(data) {

					productLoop( data.products, rowID, strProductID, strTitle, strPrice, strOptions, 10 );
					
					//loop through the products returned
					/*
					for( var i in data.products ) {
						product = data.products[i];
					//$.each(data.products, function(i,product){
						strTitle = product.title;
						strPrice += '<span id="product_prices_' + product.product_id + '" class="quantities_' + product.price_breaks +'">' + buildPriceInformation(product) + '</span>';
						strPrice = URLDecode(unescape(strPrice));
						strPrice = URLDecode(unescape(strPrice));
						strPrice = strPrice.replace(/Â/g, "");

						if (product.num_options == 1) {
							strProductID = product.product_id;
						}
						//else product options, therefore build the options string
						else {
							strProductID = '';

							strOptions += '<option value="' + product.product_id + '">';

							if(product.attribute_summary != '') {
								strOptions += product.attribute_summary;
							}
							else {
								strOptions += product.title;
							}

							strOptions += '</option>';
						}

					//});
					}
					populateQuickFields(rowID, strProductID, strTitle, strPrice, strOptions);
					*/
				}
			);
		}

		blnRunSearch = true;
	}
	
	// Timeout loop used to ease the burden on IE8-
	function productLoop( products, rowID, strProductID, strTitle, strPrice, strOptions, timeout ) {
		
		product = products.shift();
		if ( typeof product == 'undefined' ) {
			populateQuickFields(rowID, strProductID, strTitle, strPrice, strOptions);
		} else { 
			//$.each(data.products, function(i,product){
			strTitle = product.title;
			strPrice += '<span id="product_prices_' + product.product_id + '" class="quantities_' + product.price_breaks +'">' + buildPriceInformation(product) + '</span>';
			strPrice = URLDecode(unescape(strPrice));
			strPrice = URLDecode(unescape(strPrice));
			strPrice = strPrice.replace(/Â/g, "");
	
			if (product.num_options == 1) {
				strProductID = product.product_id;
			}
			//else product options, therefore build the options string
			else {
				strProductID = '';
	
				strOptions += '<option value="' + product.product_id + '">';
	
				if(product.attribute_summary != '') {
					strOptions += product.attribute_summary;
				}
				else {
					strOptions += product.title;
				}
	
				strOptions += '</option>';
			}
			
			setTimeout( function(){productLoop( products, rowID, strProductID, strTitle, strPrice, strOptions, timeout );}, timeout);
		}
	}

	// Produces a span element, which contains all price break information. The resulting element includes the following class attributes:
  //  product_price_X, were X is the product_id
  //  price_quantity_Y, were Y is the lower limit on the price break
  function buildPriceInformation(product_data) {
  	strPrice = '';

		if (product_data.price_breaks != undefined)
    {
			quantities = product_data.price_breaks.split('_');
			//loop through each price break creating the require html
			for (i = 0; i < quantities.length; i++)
      {
				//display the price associated with quantity 1 and set the active_price
				if (quantities[i] == 1) {
         	strPrice += '<span class="product_price_' + product_data.product_id + ' price_quantity_' + quantities[i] + ' active_price">';
				}
  	    else {
      		strPrice += '<span class="product_price_' + product_data.product_id + ' price_quantity_' + quantities[i] + '" style="display:none;">';
				}

      	strPrice += product_data.price_break[quantities[i]];
      	strPrice += '<span style="display:none" class="raw_price">' + product_data.price_break_value[quantities[i]] + '</span>';
      	strPrice += '<span style="display:none" class="raw_price_ex">' + product_data.price_break_ex_value[quantities[i]] + '</span>';
      	strPrice += '</span>';
      }
    }
    //else only one price, set the quantity as 1 and ensure it is the active price
   	else {
			strPrice += '<span class="product_price_' + product_data.product_id + ' price_quantity_1 active_price">';
      strPrice += product_data.price_low;
      strPrice += '<span style="display:none" class="raw_price">' + product_data.price_sale_inc_low + '</span>';
      strPrice += '<span style="display:none" class="raw_price_ex">' + product_data.price_sale_ex_low + '</span>';
      strPrice += '</span>';
		}

		return strPrice;
  }

  function productRow(strProductID){
    intExistingRow = 0;

	  //loop through the selected (single item) options
	  $('input.selected_product').each(function() {
	    if ($(this).val() == strProductID) {
	      intExistingRow = $(this).attr('id').replace(/product_option_/,'');
	      return false;
	    }
	  });

	  if (intExistingRow == 0) {
	    $('select.selected_product option:selected').each(function() {
	      if ($(this).val() == strProductID) {
	        intExistingRow = $(this).parent().attr('id').replace(/product_option_/,'');
	        return false;
	      }
	    });
	  }

	  return intExistingRow;
  }

	function populateQuickFields(rowID, strProductID, strTitle, strPrice, strOptions) {
    intProductRow = productRow(strProductID)

    //if the product exists
	  if (intProductRow != 0 && intProductRow != rowID) {
	    //remove the row
	    resetRow(rowID)

	    //set the focus to the row where the product was previously selected
	    $('#product_reference_'+intProductRow + '_quantity').focus();
	    alert('Product previously selected, please set the required quantity');

	  }
	  //else the product does not exist in the quick order
	  else {
  	  //loop through the selected options

  	//update the text boxes
  		//update the description box
  		$('#product_reference_' + rowID + '_name').empty();
  		$('#product_reference_' + rowID + '_name').text(strTitle);
  		$('#product_reference_' + rowID + '_options').empty();
  		$('#product_reference_' + rowID + '_price').empty();

  		//update the prices box
  		$('#product_reference_' + rowID + '_price').html(strPrice);

  		//if there are options, update the options box and clear the prices whilst no options are selected
  		if (strOptions) {
  			//wrap options in the select with a default value
  			strOptions = '<div><select class="selected_product" name="product_option[]" id="product_option_' + rowID + '" onchange="updateQuickOrderPrices(' + rowID + ');"><option value="">-- Please Choose --</option>' + strOptions + '</select></div>'

  			//add the reference and the options to the description box
  			$('#product_reference_' + rowID + '_options').html(strOptions);

  			//hide the price when no option is selected, this avoids all possible prices being used in the sub-total
  			$('#product_reference_' + rowID + '_price .active_price').hide();
  			$('#product_reference_' + rowID + '_price .active_price').removeClass('active_price');

  		}
  		// when the product does not include any options, bind the qty box event
  		// NOTE. when options are available, the change in option will bind the correct event to the qty box
  		else {
  			//rebind the qty box
  			rebindQuantityEvents(rowID, strProductID);
  			/*
  			$('#product_reference_' + rowID + '_quantity').unbind('blur');
  			$('#product_reference_' + rowID + '_quantity').bind('blur', function (){
  	        	quantityChanged(strProductID, rowID);
        		});
        */

        	//add a hidden input to the options box containing the product id
        	//wrap options in the select with a default value
  			  strOptions = '<input type="hidden" class="selected_product" name="product_option[]" id="product_option_' + rowID + '" value="' + strProductID + '" />';

  			  //add the reference and the options to the description box
  			  $('#product_reference_' + rowID + '_options').html(strOptions);

  			  updateSubTotal();
        }

        //bind the delete event
        $('#product_reference_' + rowID + '_delete').parent().unbind('click');
        $('#product_reference_' + rowID + '_delete').parent().bind('click', function() {
  			    resetRow(rowID);
        });

      //add new row, if required
  		addNewRow();
		}

		rebindQuantityEvents(rowID, strProductID);
	}


	// adds a new
	function addNewRow()
    {
      	var iRows = 1;

      	//loop through the existing rows and check if free
		while($('#quick_order_row' + iRows).length > 0) {
			//if product reference_<row_num> has data, move to the next box
        	if($('#product_reference_' + iRows).val() != '') {
          		iRows++;
        	}
        	else {
          		return
        	}
      	}

      	//NOTE. Should only reach here if there are no free rows for another product (i.e. new row is required)

      	strNewRowHTML = '<tr id="quick_order_row' + iRows + '">';
        strNewRowHTML += '<td class="row_number">' + iRows + '</td>';
        strNewRowHTML += '<td class="product_reference"><input type="text" class="textbox_code ajax_product_search" name="product_reference[<?=$iRows?>]" id="product_reference_' + iRows + '" value="" /></td>';
        strNewRowHTML += '<td class="product_quantity" align="center" >';
        strNewRowHTML += '<table cellpadding="0" cellspacing="0">';
        strNewRowHTML += '<tr>';
        strNewRowHTML += '<td><img src="/images/img_minus.gif" class="quantity_link" id="product_reference_' + iRows + '_minus" alt="-" /></td>';
        strNewRowHTML += '<td><span><input type="text" name="multi_quantity[]" id="product_reference_' + iRows + '_quantity" class="quick_qty" value="1" /></span></td>';
        strNewRowHTML += '<td><img src="/images/img_plus.gif" class="quantity_link" id="product_reference_' + iRows + '_plus" alt="+" /></td>';
        strNewRowHTML += '</tr>';
        strNewRowHTML += '</table>';
        strNewRowHTML += '</td>';
        strNewRowHTML += '<td class="product_name"><span id="product_reference_' + iRows + '_name">&nbsp;</span></td>'
        strNewRowHTML += '<td class="product_options"><span id="product_reference_' + iRows + '_options">&nbsp;</span></td>'
        strNewRowHTML += '<td class="product_price"><span id="product_reference_' + iRows + '_price">&nbsp;</span></td>'
        strNewRowHTML += '<td class="product_delete"><span id="product_reference_' + iRows + '_delete">&nbsp;</span></td>'
        strNewRowHTML += '</tr>'

      	//insert the new row after the last product row (i.e. before the sub total.
      	$(strNewRowHTML).insertAfter('#quick_order_row' + (iRows - 1));

      	//TODO
      	//bind the events to the product search and the delete
      	// NOTE. Do not bind the quantity box until a product has been entered.
      		//bind event to the product code search box
      		initQuickBuySearchButtons();
    		initQuickOrderTextBoxes();

      	//set the focus to the new box
      	$('#product_reference_'+iRows).focus();
    }

    function initQuickBuySearchButtons(){
      $('.ajax_product_search').unbind('blur');
      $('.ajax_product_search').keydown(function(e)
      {
        if(e.keyCode == 13) {
          strTemp = $(this).attr('id');
          strID = strTemp.replace(/product_reference_/, '');
          //alert(strID + '/' + $(this).val());
          runQuickOrderProductSearch($(this).val(), 'product_reference_' + strID);
          return false;
        }
      });
      $('.ajax_product_search_button').bind('click', function() {
        //alert('woo');
        runQuickOrderProductSearch($('#product_reference_' + this.name).val(), 'product_reference_' + this.name);
        return false;
      });
    }

    function initQuickOrderTextBoxes()
    {
      $('.ajax_product_search').blur(function () {
        objTextBox = $('#'+$(this).attr('id'));
        runQuickOrderProductSearch(objTextBox.val(), $(this).attr('id'));
      });

      $('.ajax_product_search').keydown(function(e) {
        if(e.keyCode == 13)
        {
          objTextBox = $('#'+$(this).attr('id'));
          runQuickOrderProductSearch(objTextBox.val(), $(this).attr('id'));
        }
      });


      //bind the delete events to the buttons
      $('.product_delete').each(function () {
		    rowID = $(this).parent().attr('id').replace(/quick_order_row/,'');

		  $('#product_reference_' + rowID + '_delete').parent().unbind('click');
      	$('#product_reference_' + rowID + '_delete').parent().bind('click', function() {
			    resetRow(rowID);
      	});

      });
    }

    function runQuickOrderProductSearch(strValue, strID)
    {
      if (blnRunSearch) {
        //alert(strValue + '/' + strID);
        blnRunSearch = false;
        //window.setTimeout('alert("' + strValue + '"); blnRunSearch = true;', 300);
        window.setTimeout("ajaxQuickOrderProductSearch('" + strValue + "', '" + strID + "');", 300);
      }
    }


    function updateQuickOrderPrices(strRowID) {
      strProductID = $('#product_option_' + strRowID).val();

    	//if an option is selected update the price
  		if (strProductID != '') {

        intProductRow = productRow(strProductID);

        //test if the product has already been selected
        if (intProductRow != strRowID) {

          $('#product_option_' + strRowID).val('');

          //set the focus to the row where the product was previously selected
	        $('#product_reference_'+intProductRow + '_quantity').focus();
	        alert('Product previously selected, please set the required quantity');
	      }
	      //else is a newly selected product, rebind the quantity
        else {
          rebindQuantityEvents(strRowID, strProductID);
			    quantityChanged(strProductID, strRowID);
			  }
		  }
    }


    //updates the price per item when the quantity is changed (uses price breaks)
    function quantityChanged(product_id, row_id){

		//select the available quantities for this particular product id
    	price_break_quantities = $('#product_prices_' + product_id).attr('class').replace(/quantities_/, '').split('_');
		
    	quantity_price_to_use = 1;
    	selected_quantity = $('#product_reference_' + row_id + '_quantity').attr('value');
    	
    	//loop through each price (break) and locate the quantity associated with the selected quantity
    	for (i = 0; i < price_break_quantities.length; i++) {
			//if selected quantities is less than or equal to price quantities use that price
    		if ((parseInt(selected_quantity)) >= (parseInt(price_break_quantities[i]))) {
    			quantity_price_to_use = price_break_quantities[i];
    		}
    	}


    	//hide all prices and remove the current active price
      	$('#product_reference_' + row_id + '_price .active_price').hide().removeClass('active_price');

      	//set the active price and show the correct price based on the quantity selected
      	$price = $('#product_reference_' + row_id + '_price #product_prices_' + product_id + ' .price_quantity_' + quantity_price_to_use)
      	//if( $price.length == 0 )
      	//	$price = $('#product_reference_' + row_id + '_price #product_prices_' + product_id + ' span:eq(0)');
      		
      	$price
      		.addClass('active_price')
      		.show();
      		
    	//update the sub-total based on the new quantity and price
    	updateSubTotal();
    }


	//sets the sub-total price in the .quick_total_price cell
    function updateSubTotal(){
    	sub_total = 0;
    	sub_total_ex = 0;
      strWishlist = '';

    	$('.active_price').each(function() {

    		row_id = $(this).parent().parent().attr('id').replace(/[^0-9]/g, '');

    		quantity = $('#product_reference_' + row_id +'_quantity').attr('value');
    		sub_total = (sub_total + (quantity * $(this).children('.raw_price').text() * 1) * 1);
    		sub_total_ex = (sub_total_ex + (quantity * $(this).children('.raw_price_ex').text() * 1) * 1);

        strWishlist += '<input type="hidden" name="multi_products['+$('#product_option_'+row_id).val()+']" value="'+quantity+'" />';
    	});

    	$.getJSON('/ajax/formatprice?inc='+sub_total+'&ex='+sub_total_ex+'&random='+Math.floor(Math.random()*10001), function(data) {
    		$('.quick_total_price').html(data);
    	});
      if($('#wishlist_products').length>0)
      {
        $('#wishlist_products').html(strWishlist);
      }
    }


    function resetRow(rowID){
    	//unbind the qty events
    	$('#product_reference_' + rowID + '_quantity').unbind('change');
    	$('#product_reference_' + rowID + '_plus').unbind('click');
    	$('#product_reference_' + rowID + '_minus').unbind('click');

    	$('#product_reference_' + rowID).val('');
    	$('#product_reference_' + rowID + '_name').empty();
    	$('#product_reference_' + rowID + '_options').empty();
    	$('#product_reference_' + rowID + '_quantity').val('1');
    	$('#product_reference_' + rowID + '_price').empty();

    	updateSubTotal();

    }


    function rebindQuantityEvents(strRowID, strProductID){
      //rebind the quantity box
  		$('#product_reference_' + strRowID + '_quantity').unbind('change');
  		$('#product_reference_' + strRowID + '_quantity').bind('change', function (){
          quantityChanged(strProductID, strRowID);
        });

      //rebind the quantity plus button
      $('#product_reference_' + strRowID + '_plus').unbind('click');
  		$('#product_reference_' + strRowID + '_plus').bind('click', function (){
  		    $('#product_reference_' + strRowID + '_quantity').val(($('#product_reference_' + strRowID + '_quantity').val() * 1) + 1);
          quantityChanged(strProductID, strRowID);
        });

      //rebind the quantity minus button
      $('#product_reference_' + strRowID + '_minus').unbind('click');
  		$('#product_reference_' + strRowID + '_minus').bind('click', function (){
  		  intCurrentQty = $('#product_reference_' + strRowID + '_quantity').val() * 1;

  		  if (intCurrentQty > 1) {
  		    $('#product_reference_' + strRowID + '_quantity').val(intCurrentQty - 1);
  		    quantityChanged(strProductID, strRowID);
  		  }

      });
    }
