SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 34
  1. #1
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    need suggestion with calculator script logic

    html page

    js page

    I need a suggestion on how to handle a part of this script. Right now function processSelection() decides if a number was clicked on the calculator or if +, -, *, or / was clicked and calls the appropriate function.

    Code JavaScript:
    function processSelection()
    {
    	var theId = this.id;
    	var button = parseFloat(theId);
     
    	if(!isNaN(button))
    	{
    		displayNumber(button);
    	}
    	else
    	{
    		switch(theId)
    		{
    			case "c":
    				clearDisplay();
    				break;
    			case "+":
    			case "-":
    			case "*":
    			case "/":
    				updateSymbol(theId);
    				break;
    			case "=":
    				equals();
    				break;
    			default:
    		}
    	}
    	return false;
    }

    Which seems to be working fine. The problem is when +, -, *, or / is clicked I'm currently calling updateSymbol(). This is where i get stuck. I'm not sure how to keep track of the initial value and lets say, a plus sign, and wait for the user to enter another number and then possibly hit equals. I was assigning these values to global variables at the top this quickly became cumbersome. I suppose I'm asking for help with the logic I need to for this. Thanks.

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    You could store the total and the operator as properties of the calculator, so that when a number is pressed you can then apply that number to the appropriate operation on the total.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hm, I think I understand.. it seems much more feasible than juggling global variables. But, how can I store totals and operators as properties of the calc?

  4. #4
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    What do you think that you can do with the following idea?

    Code javascript:
    if (parseInt(theId, 10)) {
        this.number = parseInt(theId, 10);
    } else {
        switch(theId) {
            case '+':
                this.operator = plus;
                break;
            case '-':
                this.operator = minus;
                break;
            case '*':
                this.operator = times;
                break;
            case '/':
                this.operator = divide;
                break;
            case '=':
                equals(this);
                break;
            case 'c':
                clearDisplay(this);
                break;
        }
    }
    function plus(num1, num2) {
        return num1 + num2;
    }
    ...
    function equals(calc) {
        this.total = calc.operator(this.total, calc.number);
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  5. #5
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I don't understand that code. Take this for example:

    Code JavaScript:
    if (parseInt(theId, 10)) {
        this.number = parseInt(theId, 10);
    }

    If there was a number, say, 83.3, I thought parseInt would return 83, but the user may enter 83.3. I used parseFloat because I thought that would return 83.3 in this case.

    Also is that snippet saying -- if this is a number then this.number = that number? Where would number be declared?

  6. #6
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    I suspected that the value of theId is going to be one of the calculator buttons, either a symbol or a digit from 0 to 9. So based on this reasoning, using parseInt will allow us to filter out the number digits of the calculator from the other keys.

    You don't need to declare the methods of objects. Given that the object already exists, you can create methods of any name that you desire.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  7. #7
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    hm, I getting it.... slowly. So taking your example. Let's say a user wants 10 minus 9. My logic (which may have been backwards) was to let the user click one then zero. When they click minus, the current value on screen would be captured and stored, minus sign would be remember in a variable and we wait (somehow) for another number to be entered and after equals is hit, display the result.

    I THINK what you're saying is when the user clicks 1 stored that in a variable, when they hit zero concatenate that with the 1...............

    and I'm lost in the logic. This is my problem, I'm not sure how to best handle remembering of values. I think your example above covers this. Please explain.

  8. #8
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    I haven't coded up a sample of this myself, but when something other than a digit is pressed, the total shown on the display should be saved out as the total

    10 + 13 =

    1 -> update the display with 1
    0 -> update the display with 10
    + -> assign operator to plus, and assign this.total = display
    1 -> update the display with 1
    3 -> update the display with 13
    = -> assign this.total = operator(total, display) and update the display
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  9. #9
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    from the switch case

    Code JavaScript:
    switch(theId) {
            case '+':
                this.operator = plus;
                break;
            case '-':
                this.operator = minus;
                break;
            case '*':
                this.operator = times;
                break;
            case '/':
                this.operator = divide;
                break;
            case '=':
                equals(this);
                break;
            case 'c':
                clearDisplay(this);
                break;
        }

    what does 'this' refer to, theID?

  10. #10
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    The this keyword refers to the calculator itself.

    I presume that the calculator has an event that watches for any mouse clicks. If that's the case then the this keyword refers to the calculator itself.

    If the key itself is firing off the event, then you'll need to use some more explicit way to access the calculator, such as document.getElementById('calc')
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  11. #11
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi,

    I really appreciate your help, I just don't understand this advice. I think I might be getting a head of myself so I scaled down what I'm trying to do to just addition. so right now all i'm concerned with is the number buttons and the plus sign.

    page here

    js here

    what i have so far..

    this function applys event handlers to all anchors on the page:
    Code JavaScript:
    var allAs = document.getElementsByTagName("a");
    for(var i = 0; i < allAs.length; i++)
    {
    	allAs[i].onclick = processSelection;
    }

    next, the id of those anchors are checked. if the id is a number its displayed on screen. if it's a plus sign performOperation(theId) is called.
    Code JavaScript:
    function processSelection()
    {
    	var theId = this.id;
    	var button = parseFloat(theId);
     
    	if(!isNaN(button))
    	{
    		displayNumber(button);
    	}
    	else
    	{
    		switch(theId)
    		{
    			case "c":
    				clearDisplay();
    				break;
    			case "+":
    				performOperation(theId);
    				break;
    			case "=":
    				equals();
    				break;
    			default:
    		}
    	}
    	return false;
    }

    the problem is my logic I have been using in

    Code JavaScript:
    function performOperation(oper)
    	{
     
    	}

    Can someone please give me an example of how performOperation() can handle repeated additions and the result will be held in a variable. and if possible please explain the code I'm rather new to this. Thanks.

  12. #12
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    If you will accept it, I'll come up with a solution for you by tomorrow that can be easily extended to work with the rest of it.

    The central crux of the solution is to use the calculator element as an object itself to store things like totals and recently clicked buttons. That way instead of having global variables floating about all over the place, they're tied to the calculator that you're using.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  13. #13
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    Okay, here's an update of your script that gets the operations working with the plus button, and can be easily extended to work with the rest of the calculator.

    Code javascript:
    var calc = document.getElementById("calc");
    calc.onclick = processSelection;
    calc.display = document.getElementsByTagName("input")[0];
    initDisplay(calc);
    function initDisplay(calc) {
    	calc.number = 0;
    	calc.newNumber = 0;
    	clearDisplay(calc);
    }
    function processSelection(evt) {
        evt = evt || window.target;
        var targ = evt.target || evt.srcElement;
    	var theId = targ.id;
    	var button = parseFloat(theId);
    	if(!isNaN(button)) {
    		displayNextDigit(button, this);
    	} else {
    		switch(theId) {
    			case "c":
    				clearDisplay();
    				break;
    			case "+":
    				this.operation = plus;
    				break;
    			case "=":
    				equals(this);
    				break;
    			default:
    		}
    		storeNumber(calc);
    	}
    	return false;
    }
     
    function storeNumber(calc) {
    	calc.number = calc.newNumber;
    	calc.newNumber = 0;
    }
    function displayNextDigit(num, calc) {
    	calc.newNumber = parseFloat(calc.newNumber) * 10 + parseFloat(num);
    	displayNumber(calc.newNumber, calc);
    }
    function displayNumber(num, calc) {
    	calc.display.value = num;
    }
    function clearDisplay(calc) {
    	displayNumber(0, calc);
    }
     
    function plus(num1, num2) {
    	return parseFloat(num1) + parseFloat(num2);
    }
    function equals(calc) {
    	var total = calc.operation(calc.number, calc.newNumber);
    	clearDisplay(calc);
    	displayNumber(total, calc);
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  14. #14
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Wow Paul thanks for writing this! I have a few questions about it..

    I see calc being passed around a lot. Take

    Code JavaScript:
    function initDisplay(calc) {
        calc.number = 0;
        calc.newNumber = 0;
        clearDisplay(calc);
    }

    for example. By saying calc.number, does that mean we are giving the calculator object a new property? So just by that fact that it has a new property we can reference it anywhere else in the program, such as

    Code JavaScript:
    function storeNumber(calc) {
        calc.number = calc.newNumber;
        calc.newNumber = 0;
    }

    also is the reason calc is being passed from function to function so the function its being passed to can see all the previously declared properties for calc?

  15. #15
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    Quote Originally Posted by tictike View Post
    Wow Paul thanks for writing this! I have a few questions about it..

    I see calc being passed around a lot. Take

    Code JavaScript:
    function initDisplay(calc) {
        calc.number = 0;
        calc.newNumber = 0;
        clearDisplay(calc);
    }

    for example. By saying calc.number, does that mean we are giving the calculator object a new property?
    The functions could all have been written without having the calc variable passed around, but it's best to write them with it there, so that you know exactly what the function requires to work properly.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  16. #16
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Does writing calc.number mean we are creating the property 'number' for calc? And since it now exists in the program, does that mean we can reference it anywhere from within?

  17. #17
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    That's correct.

    Some of the code should be further refined too, because passing a reference to the calc object should be avoided when a more clearly defined reference can be used. For example, here is one of the functions tidied up:

    Code javascript:
    function displayNumber(num, display) {
        display.value = num;
    }
    function clearDisplay(calc) {
        displayNumber(0, calc.display);
    }
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  18. #18
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I'm getting it, slowly.

    I get lost with

    Code JavaScript:
    case "+":
                    this.operation = plus;
                    break;

    because, the + button is clicked, then we go to 'plus'

    Code JavaScript:
    function plus(num1, num2) {
        return parseFloat(num1) + parseFloat(num2);
    }

    but where do num1 and num2 come from?

  19. #19
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    Ahh, we don't go to plus. If it was plus() then we would run the function, but it's plus just by itself so that only a reference to the plus function is assigned.

    By pointing calc.operation to the plus function, we can call plus() by performing calc.operation(n1, n2). The clever idea there is that calc.operation could be pointing to any individual function such as minus or times, and calc.operation(n1, n2) returns the appropriate response.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  20. #20
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ahh, I see I'm just about ready to extend this for the rest of the calculator's functions but there are 2 more things I'm not sure about. one is this line:

    calc.newNumber = parseFloat(calc.newNumber) * 10 + parseFloat(num);

    from:

    Code JavaScript:
    function displayNextDigit(num, calc) {
        calc.newNumber = parseFloat(calc.newNumber) * 10 + parseFloat(num);
        displayNumber(calc.newNumber, calc);
    }

    Why multiple by 10 and then add num?

  21. #21
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    That is so that we don't need to apply special logic for is the 0 is already there.
    Instead, by shifting the digits left by one space (multiply by 10) and adding on the new number, it works as expected for all situations, whether it's 0 or not.

    Later on when you add in support for the decimal point, the code will also be easier to modify.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  22. #22
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Why is storeNumber(calc); inside of processSelection()?

  23. #23
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,526
    Mentioned
    83 Post(s)
    Tagged
    3 Thread(s)
    It shouldn't be inside of processSelection. It should be just after it.

    Here is how the functions should be organised

    initDisplay
    processSelection
    storeNumber
    displayNextDigit
    displayNumber
    clearDisplay
    plus
    equals

    It is possible to store functions within functions, though, and for the ones like plus and equals it may be better to encapsulate them all within an operation object. For example:

    Code javascript:
    calc.operation = {
        plus: function (num1, num2) {
            ...
        },
        minus: function (num1, num2) {
            ...
        },
        times: function (num1, num2) {
            ...
        },
        divide: function (num1, num2) {
            ...
        },
        equals: function (calc) {
            ...
        }
    };

    Then they can be assigned with

    Code javascript:
    this.performOperation = this.operation.plus;

    But that's an idea that you may want to chase down later, as a way to more easily manage the many similar operation functions.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  24. #24
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To me storeNumber(calc); is inside of processSelection(evt), so it can be deleted?

    Code JavaScript:
    function processSelection(evt) {
        evt = evt || window.target;
        var targ = evt.target || evt.srcElement;
        var theId = targ.id;
        var button = parseFloat(theId);
        if(!isNaN(button)) {
            displayNextDigit(button, this);
        } else {
            switch(theId) {
                case "c":
                    clearDisplay();
                    break;
                case "+":
                    this.operation = plus;
                    break;
                case "=":
                    equals(this);
                    break;
                default:
            }
            storeNumber(calc);
        }
        return false;
    }

    EDIT:
    Oh, I see why it's there now . but other question coming in a min.
    Last edited by tictike; Nov 3, 2008 at 14:14. Reason: i see now

  25. #25
    SitePoint Guru tictike's Avatar
    Join Date
    Apr 2008
    Location
    Canada
    Posts
    863
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not sure why some of the functions are not over writting others. For example, lets say the user clicks '4'. Eventually we get to

    Code JavaScript:
    function displayNumber(num, calc) {
        calc.display.value = num; 
    }

    and '4' is display on the calc. If next the users clicks '5', and we get to the same function, why doesn't this function erase the 4 and display 5. why does it basically concatenate the two numbers.

    To me, this function is doing the same thing

    Code JavaScript:
    function storeNumber(calc) {
        calc.number = calc.newNumber; //=4
        calc.newNumber = 0;
    }

    I don't see why every newNumber is not changing the value for number. instead its appending the new newNumber to the existing number (if there is one).


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •