Broad Network


Sending Data to a Shopping Cart at the Client for Web Development with Perl and MySQL

Web Development Basics with Perl and MySQL – Part 11

Using Apache Web Server

Foreword: In this part of the series, I explain how the opened HTML window at the client computer will send data to the shopping cart at the client, without having anything to do with the server.

By: Chrysanthus Date Published: 28 Apr 2016

Introduction

This is part 11 of my series, Web Development Basics with Perl and MySQL. In this part of the series, I explain how the opened HTML window at the client computer will send data to the shopping cart at the client, without having anything to do with the server. I assume you have read the previous parts of the series, before reaching here; this is a continuation.

Recall
Conventional web development software is one that each time the user needs information during a session, request will move from the client browser to the server and the response sent back to the client. This series teaches you how to do web development. With conventional web development, all the computing is done at the server. Active Client Pages is the opposite in the sense that most (in theory - all) of the computing is done at the client.

Today, the tools (web features) for Active Client Pages have been improved. Active Client pages come with the advantage of speed of operation (of a session). The shopping cart is a scheme where the data (information) comes from the user at the client. So any good shopping cart today should use Active Client Pages technology. That is why the shopping cart code I give you in this series uses Active Client Technology, despite the fact that this series is for conventional web development.

Data for Shopping Cart
In the project of this series, the shopping cart is contained in a floated aside element. When an item (product) in the page that has the shopping cart is clicked, a browser window opens. This window has the enlarged image of the item clicked. It has the name of the item (title, in the case of a book). It has a short summary of the item and an explanation (details) of the item. It also has an input number control for the user (client - student) to type in the number of the particular item that he wants. It has a button that when clicked, the information will go into the shopping cart. It also has another button, which when clicked will close the window and cancel the selection of the item for purchase. In this tutorial, I show you how everything said in this paragraph is coded. I will have to code the shopping cart itself first, using knowledge gained from the previous part of the series.

The Shopping Cart
Without the ECMAScript, the HTML code for the shopping cart is:

<aside style="float:right">

    <table id="AT1">
        <caption><strong>SHOPPING CART</strong></caption>
        <thead>
            <tr><th>Quantity</th><th>Item-Name</th><th>Unit-Price</th><th>Total-Price ($)</th></tr>
        </thead>
    </table>
    <table id="AT2">
        <tfoot>
            <tr><th colspan="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Grand Total:</th><th></th></tr>
        </tfoot>
    </table>

    <form method="POST" action="purchase.pl" onsubmit="return formPurchaseStr()">
        Money Transfer Email: <input type="email" name="email">
        <input type="hidden" name="purchaseStr">
        <p style="text-align:center"><button type="submit">Purchase</button></p>
    </form>

</aside>

This code and the rest of the code in this part of the series, is built from the knowledge in the previous part of the series. You should place this code in the books (and pens) HTML page, just below the start tag of the article element. In this tutorial, I will only talk about shopping cart in the books page. The same thing applies to the pens page. The aside element has a button, in an HTML Form, to place the order. The Form has an email input tag for the user’s Paypal or MoneyBookers email address. The Form also has a hidden input control, whose purpose I will explain later.

The Items Array
Each items (books or pens) page has the items array. The items array has the explanations (details) of all the items (4 of them) displayed on a web page. Each item has a corresponding explanation in the array. Item (image) of index 0, has its explanation at index 0 of the array; item of index 1 has its explanation at index 1 of the array, item of index 2, has its explanation at index 2 of the array; and so on.  This is the array and content for the first page of the project:

<script type="text/ecmascript">
    itemsArr = new Array("Some fine details 0…", "Some fine details 1…", "Some fine details 2…", "Some fine details 3…");
</script>

This array has to be hard coded in the first page, so type it (including the script tags) in the books and pens page, just before the end tag  (</article>) of the article element.

Opening a Window
Each image has the onclick event attribute as follows:

        onclick="openWin(index)"

where index is an integer from zero to 3, for the 4 images. So, when an image is clicked, the “openWin()” function is called. It is you, the web developer, to code (type out) this function. You can code this function in the aside element or outside it, but in the same page. This function opens the window and sends the relevant information to the window.

This is the openWin() function, which I suggest you code in the aside element in an ECMAScript.

        function openWin(indx)
            {
                //determine row and cell numbers
                var rowNo;
                var cellNo;
                if (indx != 0)
                    rowNo = parseInt(indx / 2);
                else
                    rowNo = 0;
                if (indx != 0)
                    cellNo = indx % 2;
                else
                    cellNo = 0;
                //obtain the item name and price with regex
                regex = /<br>.+<br>/;
                subject = document.getElementById('B1').rows[rowNo].cells[cellNo].innerHTML;
                name = subject.match(regex);
                name = name.toString();
                itemName = name.replace(/<br>/g, "");  
                itemName = itemName.replace(/\ Price\: \$\d{0,3}\.\d{2,2}/, "");  
                price = subject.match(/\d{0,3}\.\d{2,2}/);  //to obtain the price
                //form the string content for the opened window
                docHTML = "<html><head><title>Choose Number of Items</title></head><body>";
                docHTML += document.getElementById('B1').rows[rowNo].cells[cellNo].innerHTML;
                docHTML += "<br>" + itemsArr[indx];
                docHTML += "<p>No. of Items: <input type='number' id='no'></p>";
                docHTML += "<button type='button' onclick='saveData()'>Send to Shopping Cart</button> <button type='button'

onclick='window.close()'>Cancel</button> <input type='hidden' id='itemName' value='" + itemName + "'> <input type='hidden'

id='price' value='" + price + "'>";
                docHTML += saveDataStr;
                docHTML += "</body></html>";
                //open window and insert info
                winRef = window.open("", "_blank", "width=900,height=600,scrollbars=yes,resizable=yes");
                winRef.document.write(docHTML);

            }

The function body has 4 segments (sub segments). The first one determines the row number and cell number of the item in the table. Remember, this table is different from the shopping cart table(s). The second segment obtains the item name and price from the table cell using regular expression techniques. The third segment forms the content of the window that will be opened. The content is formed as a string. The fourth segment opens an empty window and sends the sting whose value is to become the content of the window.

I will explain just the first sub segment. If you have covered the prerequisite to begin this series, then you should be able to read the other 3 segments and understand. The first segment has two if-constructs. The first if-construct is to determine the row index that has the item (product). The second is for the cell index that has the item.

Let us first see how the row index is determined: The argument of the openWin(indx) function is the index of the item in the items table (this is not a the shopping cart table in the aside element). In this project the indexing is from 0 to 3, for the 4 items. You can have it from 1 to 4 if you want to, however, indexing in computing is generally from 0. Now, there are 2 columns for the items table. So in order to know which has the item, you have to use the expression, “parseInt(indx/2)”. This expression divides the index received by 2 and returns the integer part of the answer. It divided by 2 because there are 2 columns. In this case, it returns a row number (index) beginning from 0. The possible numbers (indices) for the rows are 0, 1, 2, and 3, beginning from zero. Now, programming does not allow 0/0; that is why you have the else block and the if condition (indx != 0).

In this table, since there are 2 columns, the indices of the cells in a row go from 0 to 1. So, to determine the cell index from item index received, you have to use the expression, “indx % 2”. This expression divides the item index by 2 and returns the remainder. The number 2 is used because there are 2 columns. So if the item (product) index received is 1, the expression returns 1; if the index is 2, the expression returns 0, if the index is 3 the expression returns 1. In this project, the highest value of the item index is 3. If it had to go on to 4, then the return value would be 0; if it had to go on to 5, the return value would be 1; and so on. The problem of dividing by zero also occurs here. That is why you have the else block and the if-condition (indx != 0) in the determination of the cell number (cellNo).

Updating the Shopping Cart
Here, we see how the shopping cart is updated each time the user selects an item for purchase. There are two functions here: the timer function and another function called, udateCart(). The timer function calls the udateCart() function every second. It is unlikely that the user will select more than one item within one second.

There is a global variable named, newStoreStr. When the user types in the number of a particular item that he wants and then clicks “Send to Shopping Cart” in the opened window, the data for the item to purchase will be sent as a string value to the newStoreStr variable (in the opener page). This value is read every second and compared with the previous one. If there is a difference it means the user has just selected an item for purchase; in this case the shopping cart tables are updated. If there is no difference, nothing happens to the shopping cart tables. Remember, the shopping cart tables hold the values that will be used to place the order.

The timer function, which should be in an ECMAScript in the aside element, is:

        ti = window.setInterval("udateCart()", 1000);

Here, 1000, means 1000ms, that is 1s. This timer function calls the udateCart() function every second. The command, which clears (stops) this timer should be placed as an attribute in the HTML start body tag; it is,

    onunload="window.clearInterval(ti)"

The udateCart() function that has to be placed in an ECMAScript in the shopping cart aside element, is:

        oldStoredStr = "";
        newStoreStr = "";

        function udateCart()
            {

                if (oldStoredStr != newStoreStr)
                    {
                        arr = newStoreStr.split(/&/);
                        quantityArr = arr[0].split(/=/);
                        quantity = quantityArr[1];
                        itemNameArr = arr[1].split(/=/);
                        itemName = itemNameArr[1];
                        priceArr = arr[2].split(/=/);
                        price = priceArr[1];

                        //insert a new empty row to the big shopping cart table.
                        document.getElementById("AT1").insertRow(-1);
                        //determine the number of rows in shop big table
                        numRows = document.getElementById("AT1").rows.length;
                        newRowIndex = numRows - 1;
                        //insert empty cells into new row - there are 4 cells
                        for (i=0; i<4; ++i)
                            {
                                document.getElementById("AT1").rows[newRowIndex].insertCell(i);
                            }

                        //insert content into cells
                        document.getElementById("AT1").rows[newRowIndex].cells[0].innerHTML = quantity;
                        document.getElementById("AT1").rows[newRowIndex].cells[1].innerHTML = itemName;
                        document.getElementById("AT1").rows[newRowIndex].cells[2].innerHTML = price;
                        //calculate and place the total price for the row
                        document.getElementById("AT1").rows[newRowIndex].cells[3].innerHTML = parseInt(quantity) * parseFloat(price);

                        //Determine the grand total and place it in the small shop table
                        grandTotal = 0;
                        for (j=1; j<numRows; ++j)   //header (th) is not included
                            {
                                grandTotal += parseFloat(document.getElementById("AT1").rows[j].cells[3].innerHTML);
                            }
                        document.getElementById("AT2").rows[0].cells[1].innerHTML = grandTotal;

                        //reset oldStoredStr
                        oldStoredStr = newStoreStr;
                    }
            }

This function works with two variables, which are:  oldStoredStr and newStoreStr. We have already talk about newStoreStr, which holds the data in string form for an item to be purchased. It is this data that will be sent to one row of the big table of the shopping cart. oldStoredStr holds the data of the previously selected item for purchase from the opened window. The udateCart() function is largely made up of an if-construct. This if-construct compares the values of the oldStoredStr variable and the newStoreStr variable. If the values are the same, it means the user has not yet selected a new item for purchase. If they are different, it means the user has just selected a new item for purchases, and the block of the if-construct is executed to place a new row in the shopping cart (big table). Remember, the udateCart() function is called every second.

The block of the if-construct of the udateCart() function, begins by splitting the string value of newStoreStr, and extracting the values to be placed in the next row of the big table in the shopping cart. Next it goes on to insert an empty row with empty cells in the shopping cart big table. Then it inserts the values for the cells. It then calculates the total price for the row and the grand total for all the items.

Finally it assigns the value of newStoreStr to oldStoredStr. At this point, the 2 variables acquire the same values. Just after this point (time), the if-block of the udateCart() function cannot be executed. As soon as the user selects a new item for purchase in the opened window, the value of newStoreStr is changed and the two values become different; and the if-block of the udateCart() function is executed the next second.

Making the Shopping Carts in Different Pages be the Same
You should have a sessionStorage variable that holds all the data of the shopping cart in a string. This variable string starts with zero length and increases as the rows of the shopping cart are added. So the variable string is appended each time a row is added. The best place to put the code to append the string is in the if-construct of the udateCart() function. The shopping cart should have a sign to indicate to the user that he has to refresh (onload - reload) the shopping cart page each time he opens the page. During this refresh short period, all the shopping cart rows of the big table and the value for the grand total are deleted; and then, are replaced with the string value of the sessionStorage variable. It may be good to have another sessionStorage variable for the grand total. I     leave the coding of this issue (same cart at different pages) as an exercise for you.

Time to take a break. Let us stop here and continue in the next part of the series.

Chrys

Related Links

Web Development Basics with Perl and MySQL
Perl Validation of HTML Form Data
Page Views with Ajax and Perl and MySQL
Web Live Text Chart Application using Perl and MySQL
Search Within a Site using Perl and MySQL
More Related Links
Perl Mailsend
PurePerl MySQL API
Perl Course - Professional and Advanced
Major in Website Design
Web Development Course
Producing a Pure Perl Library
MySQL Course

BACK NEXT

Comments

Become the Writer's Follower
Send the Writer a Message