/    Sign up×
Community /Pin to ProfileBookmark

Cannot Access Form Controls with JS After innerHTML redraw

Gentlemen,

I have recently upgraded a part of a system for a customer. It is an online “cash register” designed to allow orders to be put through quickly. It is composed somewhat like a spreadsheet, with rows for each product, then sub total etc at the bottom. There is a form/row for adding a new product, a form/row for each product loaded, and a final form holding the sub total, grand total and other values.

Using a div with the InnerHTML function and an Ajax call, I was able to update it recently so that only the products list in the div refreshes, and returned values set the sub total and so forth, removing the need for screen redraws completely. However, there is a problem.

Chrome works fine, but Opera and Firefox share a common problem. Although I can go in and say increase or decrease a quantity and have it recalculate the total, as soon as I add the next product and the innerHTML is called, this ability is lost. Triggering the totalling code (by change quantity or discount) produces an error like the form control is not even there.

It’s like the browsers have lost the ability to address the form after the innerhtml call. It is almost as if certain other things need to be refreshed in memory, though my researches so far have been fruitless.

Does anyone know how to solve this?

Thanks,
Joel.

to post a comment
JavaScript

10 Comments(s)

Copy linkTweet thisAlerts:
@xelawhoFeb 16.2012 — hard to say on the face of it. are you getting any errors in te error console? do you have a link or some sample code?
Copy linkTweet thisAlerts:
@NZWebGuyauthorFeb 16.2012 — OK here's a simple look at the div structure that gets redrawn with every add product/delete product operation...

<div id="Ajax_Content" style="height: 210px; width: 980px; overflow: scroll;">

<table cellpadding="5" cellspacing="1" border="0" align="center">

<tr class="row1">

<th align="right" class="roundHeading">No: 1</th>

<th align="left" class="roundHeading">Product</th>

<th align="right" class="roundHeading">Qty</th>

<th align="right" class="roundHeading">Price</th>

<th align="right" class="roundHeading">Disc. %</th>

<th align="right" class="roundHeading">Sold For</th>

<th align="right" class="roundHeading">Amount</th>

<th align="left" class="roundHeading">&nbsp;</th>

<th align="left" class="roundHeading">&nbsp;</th>

</tr>

<form name="Add_Line_Form" method="POST" target="ajaxFrame" action="ajax.php?page=stock_control/customer_orders_common/add_product_to_customer_order">

<input name="Product_ID" id="Product_ID" type="hidden" value="">

<input name="Supplier_ID" id="Supplier_ID" type="hidden" value="">

<input name="Add_Line_Form" id="Add_Line_Form" type="hidden" value="Yes">

<tr class="row1">

<td align="right"><b>1.</b></td>

<td nowrap>

<input tabindex="1" style="text-align: center;" type="text" name="Product_Code" size="7" maxlength="20" onChange="ajax_product_lookup(this.value, 'Offline Order', 43413, 'Add_Line_Form', 0);" autofocus />

<input type="button" value="L" title="Find a Product" onclick="product_lookup('Offline Order', 43413, 'Add_Line_Form', 0);">

<input type="text" name="Title" size="60" maxlength="100" onfocus="offline_order_title_focus();" onchange="offline_order_title_change(0);">

</td>

<td align="right" class="row1"><input type="text" name="Quantity" id="Quantity" class="number" onfocus="this.select();" size="6" maxlength="6" value="1.00" onchange="customer_order_quantity_change(1.00, 0);" tabindex="2" /></td>

<td align="right" class="row1"><input type="text" name="Retail_Price" id="Retail_Price" onFocus="this.blur();" class="row1Number" size="8" maxlength="8" value="" /></td>

<td align="right" class="row1"><input type="text" name="Discount" id="Discount" class="number" onfocus="this.select();" size="6" maxlength="6" value="0.00" onchange="customer_order_discount_calculate(0);" /></td>

<td align="right" class="row1"><input type="text" name="Price" id="Price" class="number" onfocus="this.select();" size="8" maxlength="8" value="0.00" onchange="customer_order_change_price(0.00, 0);" /></td>

<td align="right" class="row1"><input type="text" name="Amount" id="Amount" onFocus="this.blur();" class="row1Number" size="8" maxlength="8" value="" /></td>

<td align="center"><input tabindex="4" name="Save_Button" type="button" value="ADD" style="background-color: red; font-weight: bold; color: white;" onclick="add_product_to_customer_order()"></td>

<td></td>

</tr>

<input name="Total_Forms" id="Total_Forms" type="hidden" value="2">

</form>

<form name="Edit_Line_Form_1">

<input name="Add_Line_Form" id="Add_Line_Form" type="hidden" value="No">

<input name="Purchase_ID" id="Purchase_ID" type="hidden" value="89855">

<input name="Retail_Price" id="Retail_Price" type="hidden" value="139.00">

<tr class="row2">

<td align="right"><b>2.</b></td>

<td nowrap><a href="javascript:;" onclick="product_popup('0679');">0679 NUTRA GOLD HOLISTIC LARGE BREED PUPPY FOOD 15KG</a></td>

<td align="right" class="row2"><input type="text" name="Quantity" id="Quantity" class="number" onfocus="this.select();" size="6" maxlength="6" value="1.00" onchange="customer_order_quantity_change(1.00, 1);" /></td>

<td align="right">139.00</td>

<td align="right" class="row2"><input type="text" name="Discount" id="Discount" class="number" onfocus="this.select();" size="6" maxlength="6" value="0.00" onchange="customer_order_discount_calculate(1);" /></td>

<td align="right" class="row2"><input type="text" name="Price" id="Price" class="number" onfocus="this.select();" size="8" maxlength="8" value="139.00" onchange="customer_order_change_price(139.00, 1);" /></td>

<td align="right" class="row2"><input type="text" name="Amount" id="Amount" onFocus="this.blur();" class="row2Number" size="8" maxlength="8" value="139.00" /></td>

<td align="center"><input tabindex="" type="button" value="Delete" onclick="if (confirm('Delete This Product from This Sale?')) delete_purchase_from_customer_order(89855, document.Order_Details_Form.Order_ID.value);"></td>

<td align="center"><input type="checkbox" name="89855" onclick="

if (this.checked)

customer_order_mark_purchase(89855);

else

customer_order_unmark_purchase(89855);

"></td>

</tr>

</form>

</table>

</div>[/QUOTE]


Here you can see the add line form for adding new products, and a form for an already added product. Tweaking quantity or price or discount triggers code that retotals the order, updates the totals on a form at the bottom, and writes the values to the database. This code works fine under all browsers until I add or delete a product which triggers code like this...

function send_request(Action)

{

http.open('get', Action);

http.onreadystatechange = handle_response;

http.send(null);

}

function handle_response()

{

if (http.readyState == 4)

parent.body.document.getElementById('Ajax_Content').innerHTML = http.responseText;

}[/QUOTE]


The action given is a PHP script that regenerates the list of purchases for that order. This self same script is used to fill in the list of purchases on the initial loading. After an event using this code is triggered and I try to, say, modify a quantity, Chrome behaves flawlessly, but Opera and Firefox both react as if the form controls are no longer there.

Opera says...

[24/11/1974 6:53:32 p.m.] JavaScript - http://192.168.1.3/petmart/public_html/login/subpage.php?page=stock_control/customer_orders_offline/view

Event thread: change

Uncaught exception: TypeError: Cannot convert 'document.forms[Form_Number].Quantity' to object

Error thrown at line 228, column 1 in customer_order_quantity_change(Original_Quantity, Form_Number) in http://192.168.1.3/petmart/public_html/login/stock_control/customer_orders_common/customer_orders_common_javascript_functions.js:

if (Number(document.forms[Form_Number].Quantity.value) < 1)

called from line 1, column 0 in <anonymous function>(event) in http://192.168.1.3/petmart/public_html/login/subpage.php?page=stock_control/customer_orders_offline/view:

customer_order_quantity_change(1.00, 1);[/quote]


Firefox says...

Error: document.forms[Form_Number].Quantity is undefined

Source File: http://192.168.1.3/petmart/public_html/login/stock_control/customer_orders_common/customer_orders_common_javascript_functions.js

Line: 228[/quote]


Both saying the same thing essentially, that the form controls don't exist, which is not true. They are there, but the innerHTML redraw seems to have wiped them from each browser's memory.

I realised I had not tested the final iteration in Internet Explorer 9. To my considerable amazement, it appears to work flawlessly under there too as well as IE8 which is good. The current implementation of this tech is under an environment I have direct control over. I told them to upgrade to Chrome and they did. But there are other places I would like to deploy it where at least a Firefox installation is possible. I will be in a position to talk them through a browser change but would rather not have to.
Copy linkTweet thisAlerts:
@NZWebGuyauthorFeb 20.2012 — So no one has encountered something like this?
Copy linkTweet thisAlerts:
@justinbarneskinFeb 21.2012 — So no one has encountered something like this?[/QUOTE]

Opera and Firefox both react as if the form controls are no longer there, because if they have been redrawn you need to declare them locally in your functions so that the browsers get a fresh look at them on each call.
Copy linkTweet thisAlerts:
@NZWebGuyauthorFeb 21.2012 — Yes I have already deduced as much ? Point is, I have no idea how to declare them. If you would kind enough to provide some example code, I would appreciate it.
Copy linkTweet thisAlerts:
@justinbarneskinFeb 23.2012 — Well, I'm not the expert coder you would have hoped to help you through this, however I would advice to ask if you are simply rewriting with innerHTML? if so, the browsers are gummed up with the old innerHTML. Before rewriting be sure to remove the old by script-
[code=html]
<SCRIPT type="text/javascript">
function erase(){ var eDiv=document.getElementById('Ajax_Content');
while(eDiv.hasChildNodes()==true){eDiv.removeChild(eDiv.getElementsByTagName('*')[0])}

alert(eDiv.hasChildNodes())
}

</SCRIPT>

[/code]


So, I'm not the expert, IE will alert while Opera and firefox will not. I don't know why.
Copy linkTweet thisAlerts:
@NZWebGuyauthorFeb 23.2012 — Right I think I see what you are getting at, thanks.
Copy linkTweet thisAlerts:
@rjtanFeb 23.2012 — Hi!i also have the same problem. I have tried your solution but still didnot work for me. anymore idea Justine? Many Thanks. with the alert it says false. it is working fine in FF with me.
Copy linkTweet thisAlerts:
@NZWebGuyauthorMar 04.2012 — Still no luck with this. Firefox chokes with an invalid pointer error on the eDiv.removeChild(eDiv.getElementsByTagName('*')[0]) line.
Copy linkTweet thisAlerts:
@NZWebGuyauthorMar 04.2012 — There just seems to be no solution to this problem. Deleting and recreating the div fails. I also tried addressing it via document.forms[1].elements[0]. Some quick if else tests showed me Firefox still recognised the forms after a redraw, but not the elements. jQuery proved no help either. Use DOM functions might work, but would result in nightmarishly clumsy and bloated code as I tried to rebuild each row and form. A lot of "pros" seem to frown on innerHTML but to my eye there seems no simpler, cleaner solution to tasks such as mine.

Only solution seems to be to tell my customers not to use Firefox, but given the severe memory leak problems it suffers from, that's probably a good thing overall.
×

Success!

Help @NZWebGuy spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.6,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...