reptile7's JavaScript blog
Saturday, August 03, 2013
Nuts, Berries, and Input Values
Blog Entry #297

Welcome back to our ongoing discussion of the customer/shipping part of the "So, You Want A Shopping Cart, Huh?" order.html page. We have one more order.html issue to address: storage of the Customer Information / Details, Shipping Address, and Comments & Additional Information table data.

Holding on to the customer

A shopping cart visitor adds two pagetwo.html items to the cart, proceeds to the order.html page, and fills out the various order.html data tables. If the visitor submits the order form right away, then there is no need to hold onto the visitor's order.html data. But suppose the visitor goes back to pagetwo.html for whatever reason prior to submitting the form. Upon returning to order.html, the visitor should not have to reenter data into the order form fields: the original data should still be sitting in those fields, ready to go.

In The customer contact section of Blog Entry #287, we defined a ship_details Object object for holding the order.html table data. Replacing order.html with pagetwo.html in the main frame of the shopcartindex.html frameset gives rise to an order.html unload event; the order.html body element has an onunload attribute that calls an add_ship_details( ) function in the shopcartindex.html source and passes thereto the ship_details object.

<body ... onunload="parent.add_ship_details(parent.ship_details);">

The add_ship_details( ) function gives the ship_details object a shipform identifier and then individually assigns the values of the 22 inputs in the Customer Information / Details, Shipping Address, and Comments & Additional Information tables to the values of the corresponding shipform object properties.

function add_ship_details(shipform) {
    shipform.comments = parent.main.document.order.comments.value;
    shipform.f_namea = parent.main.document.order.name_first.value;
    shipform.l_namea = parent.main.document.order.name_last.value; =;
    shipform.sameflag = parent.main.document.order.same_flag.value;
    shipform.shipname = parent.main.document.order.ship_name.value;
    shipform.ad_oneb = parent.main.document.order.ship_address1.value;
    ... }

Do we really need to pass the ship_details object to the add_ship_details( ) function and give it a new name in order to assign values to its properties? Nope, not at all. Moreover, the parent references are unnecessary as we are working in the shopcartindex.html document, although there's no harm in having them there; indeed, you might want to keep them as a sign that data is being passed from a frame document to a frameset document.

Complementarily, returning to order.html causes an order.html load event; the order.html body element has an onload attribute that calls a shopcartindex.html refresh_ship_details( ) function and passes thereto the ship_details object.

<body ... onload="parent.refresh_ship_details(parent.ship_details);">

The refresh_ship_details( ) function also gives the ship_details object a shipform identifier and then individually assigns the values of shipform's properties to the values of the corresponding order form fields.

function refresh_ship_details(shipform) {
    parent.main.document.order.comments.value = shipform.comments;
    parent.main.document.order.name_first.value = shipform.f_namea;
    parent.main.document.order.name_last.value = shipform.l_namea; =;
    parent.main.document.order.same_flag.value = shipform.sameflag;
    parent.main.document.order.ship_name.value = shipform.shipname;
    parent.main.document.order.ship_address1.value = shipform.ad_oneb;
    ... }

In sum, the add_ship_details( ) function scoops up the visitor's data upon leaving the order.html page and the refresh_ship_details( ) function reloads the visitor's data upon returning to the order.html page. We're all set.

After the add_ship_details( ) function fires, the ship_details/shipform object holds onto the order.html data for as long as the visitor is at the shopping cart. If the visitor leaves and later returns to the cart, then the ship_details object is built from scratch as detailed in Blog Entry #287 (vide supra).

BTW, the Customer Information / Details table's Country field has an initial value of UK (all of the other customer/shipping fields are initially empty), but the visitor does not see this value upon arriving at the order.html page as it is cleared by the refresh_ship_details( ) function.

Filling the cookie jar

The order.html unload event is the right point at which to set in motion the otherwise-inactive* cookie functionality of the shopping cart as that functionality acts on data written to the ship_details object by the add_ship_details( ) function. The set-cookies part of the functionality (vis-à-vis the get-cookies part*) begins with the shopcartindex.html go_with_cookie( ) function. My preferred way to register the add_ship_details( ) and go_with_cookie( ) listeners on the order.html document is to put a

window.onunload = function ( ) {
    parent.add_ship_details( );
    parent.go_with_cookie( ); }

function in order.html's first script element. (*We'll see in the following entry that the get-cookies part is actually not 'inactive': it just doesn't have any cart cookies to work with.)

Here's the go_with_cookie( ) function:

function go_with_cookie( ) {
    parent.ship_details.zipa); }

The go_with_cookie( ) function calls a setCookieArray( ) function and passes it 10 arguments:
(0) a gifttails string and
(1-9) the values of the first nine fields of the Customer Information / Details table (which have just been loaded into the ship_details object by the add_ship_details( ) function, as described above).

The setCookieArray( ) function is preceded by two lines of top-level code that create a one-year-into-the-future expdate date that we'll use to set an expiration date for our cookies.

var expdate = new Date( );
expdate.setTime(expdate.getTime( ) + (24 * 60 * 60 * 1000 * 365));

It is not necessary to postdate expdate via a millisecond-based calculation: expdate.setFullYear(expdate.getFullYear( ) + 1); will do the trick.

Via a for loop whose i counter runs from 0 to 8, the setCookieArray( ) function iteratively sends gifttails+i, setCookieArray.arguments[i+1], and expdate to a setCookie( ) function.

function setCookieArray(name) {
    temp_length = setCookieArray.arguments.length - 1;
    for (var i = 0; i < temp_length; i++) {
        data = setCookieArray.arguments[i + 1];
        setCookie(name + i, data, expdate); } }

FYI: The use of arguments as a property of a Function object is deprecated.

The setCookie( ) function is called nine times: each run adds a
cookie to the shopcartindex.html document.cookie string.

function setCookie(name, value, expires) {
    if (!expires) expires = new Date( );
    document.cookie = name + "=" + escape(value) + "; expires=" + expires.toGMTString( ) + "; path=/"; }

• The escape( ) function is deprecated: use the encodeURIComponent( ) function instead.
• The toGMTString( ) method is deprecated: use the toUTCString( ) method instead.

So, if our visitor enters

Joe Blow's sample cookie info

into the Customer Information / Details table, then after unloading the order.html page, the shopcartindex.html document.cookie string will read:

gifttails0=Joe; gifttails1=Blow;; gifttails3=1234%20Main%20Street; gifttails4=; gifttails5=New%20Orleans; gifttails6=LA; gifttails7=USA; gifttails8=70118

This output assumes that there are no other cookies associated with the shopcartindex.html page.

Cookie retrieval

Let's do this next time.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)