TalkPHP

TalkPHP (http://www.talkphp.com/forums.php)
-   Javascript, AJAX, E4X (http://www.talkphp.com/javascript-ajax-e4x/)
-   -   count checkbox, radio and input.... (http://www.talkphp.com/javascript-ajax-e4x/4177-count-checkbox-radio-input.html)

allworknoplay 04-22-2009 05:47 PM

count checkbox, radio and input....
 
Ok so I gave myself a simple project...I have 6 input types.
3 are of type radio, and the other 3 are checkboxes.

JS:
Code:

<script type="text/javascript">
var getCheck = document.getElementsByName('checkbox');
var getRadio = document.getElementsByName('radio');
var getInput = document.getElementsByTagName('input');
       
 
document.write('There are: ' +getCheck.length+ ' checkboxes');
document.write('There are: ' +getRadio.length+ ' radio buttons');
document.write('There are a total of: ' +getInput.length+ ' input types');
       
</script>

HTML:
Code:

<body>
<div><input type="checkbox" name="checkbox" value="checkbox" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox" /></div>
<div><input type="radio" name="radio" /></div>
<div><input type="radio" name="radio" /></div>
<div><input type="radio" name="radio" /></div>
</body>

My output is:

There are: 0 checkboxes
There are: 0 radio buttons
There are a total of: 0 input types

I thought that the "getElementsByName and getElementsByTagName" were arrays? So I thought I could just use the ".length" to get the count?

So anyways, the output is suppose to say:

There are 3 checkboxes.
There are 3 radio buttons.
There are a total of: 6 input types.

Salathe 04-22-2009 05:59 PM

You have to wait for those DOM elements to have been loaded before you can access them with JavaScript. Either hook into the body's onload event (or DOMReady if you're feeling adventurous) or place the script below the inputs in your HTML.

Kalle 04-22-2009 06:29 PM

Like said by Salathe, you need to execute when your dom tree is fully loaded (this is called "domready"). Most frameworks includes support for the domready event, so you can bind a new domready even and execute your code then.

The fact that this does not work is because the browser does not have a 2 stage parsing/execution stage like PHP (4 and newer) does. Meaning that once this part is parsed, the browser will execute it, so when it executes your javascript code it havn't got to the HTML elements yet, making them render as 0 :)

allworknoplay 04-22-2009 06:36 PM

Thanks guys,

When I moved the JS code below the HTML, I got the output I was looking for. However, it doesn't seem "clean" to do that.

So I will look into how I can hook into the body "onLoad" event.
This way I can keep the majority of the JS code on the top part of the page...

As for Domready, the last 10 mins was the first time I ever even heard of that!!!

Kalle 04-22-2009 07:01 PM

Don't use onload, its the same as running it in <head>, domready or on the bottom of your HTML, just before </body> to emulate a domready event.

;)

allworknoplay 04-22-2009 07:20 PM

Ok, well I didn't use onLoad, because I don't really know how to use it just yet... :-(

But here's what I have, it DOESNT work, but it's what I have in mind. I am using "onLoad" in the INPUT tags *ONLY* as a placeholder because I don't know how to call the function within the INPUT tags.

JS:
Code:

<script type="text/javascript">
        var countCheck = 0;
        var countRadio = 0;
        var countInput = 0;
        var getCheck = document.getElementsByName('checkbox');
        var getRadio = document.getElementsByName('radio');
        var getInput = document.getElementsByTagName('input');
       
        function countMe(type){
       
                if(type == document.getElementsByName('checkbox')) countCheck += 1;
                if(type == document.getElementsByName('radio')) countRadio += 1;
               
       
        }
       
 
      countInput = (countCheck + countRadio);

          document.write('There are: ' +countCheck+ ' checkboxes <br />');
        document.write('There are: ' +countRadio+ ' radio buttons <br />');
        document.write('There are a total of: ' +countInput+ ' input types <br />');
       
</script>

HTML:
Code:

<body>
<div><input type="checkbox" name="checkbox" value="checkbox" onLoad="countMe(this)" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox" onLoad="countMe(this)" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox" onLoad="countMe(this)" /></div>
<div><input type="radio" name="radio" onLoad="countMe(this)" /></div>
<div><input type="radio" name="radio" onLoad="countMe(this)" /></div>
<div><input type="radio" name="radio" onLoad="countMe(this)" /></div>
</body>

So now I will explain my intentions.

As each element loads, it calls the "countMe" function.
I use the "this" to dynamically tell the function what type of element it is.

The function then just takes a look at what element it is, and adds "1" to the correct counter.

Is what I'm doing possible? How do you call a function within the INPUT tags? Everything I've looked up, it's always based on some kind of event like onClick, onFocus etc...
Is there any "passive" way to call a function without user input?

Kalle 04-22-2009 08:00 PM

What you are doing is possible yes, but! Theres no such event called onload on input tags, also you can't determine the type of the current object by comparing it like you do so in "CountMe", so you need to check if the "type" property is what you expect.

javascript Code:
switch(el.type)
{
    case('...'):
    {
        /* ... */
    }
    break;
    /* ... */
}

You may also use the increment operators (both postfix and prefix in javascript):
javascript Code:
var $variable;

++$variable;
$variable++;

--$variable;
$variable--;

/* $variable = 0 */

As for what you are trying to do, then I think something along these lines should be correct:
javascript Code:
function CategorizeInputFields()
{
    var retval =
    {
        'checkbox'0,
        'radio':    0,
        'password'0,
        'file':  0,
        'button':   0,
        'hidden':   0,
        'image':    0,
        'reset':    0,
        'submit':   0,
        'text':  0,
 
        'total':    0
    };

    /* Browser does not support getElementsByTagName, return void */
    if(!document.getElementsByTagName)
    {
        return(retval);
    }

    var elements = document.getElementsByTagName('input');
    retval.total = elements.length;

    /* No input tags in tree */
    if(!retval.total)
    {
        return(retval);
    }

    for(var n = 0; n < retval.total; ++n)
    {
        /* I'm really lazy so I'll use eval here, don't do like this! */
        eval('++retval.' + elements[n].type.toLowerCase() + ';');
    }

    return(retval);
}

function Render()
{
    var elements = CategorizeInputFields();

    document.write('There are: ' + elements.checkbox + ' checkboxes <br />');
    document.write('There are: ' + elements.radio + ' radio buttons <br />');
    document.write('There are a total of: ' + elements.total + ' input types <br />');
}

And in your HTML:
HTML Code:

<body>
<!-- input elements -->

<script type="text/javascript">
<!--
Render();
// -->

</script>
</body>


Salathe 04-22-2009 08:27 PM

Quote:

Originally Posted by Kalle (Post 23325)
javascript Code:
/* I'm really lazy so I'll use eval here, don't do like this! */
eval('++retval.' + elements[n].type.toLowerCase() + ';');

javascript Code:
/* Don't be lazy! */
++retval[elements[n].type.toLowerCase()];

allworknoplay 04-22-2009 09:17 PM

Quote:

Originally Posted by Salathe (Post 23326)
javascript Code:
/* Don't be lazy! */
++retval[elements[n].type.toLowerCase()];

haha, you guys crack me up...


Ok, so it works now, I see where you went with the code. Although the "output" is written up on top, by using the Render() function after the elements have already loaded, you can now output the correct number of elements instead of diplaying 0.
gotchya...I have some questions about the CategorizeInputFields function, so I'll break it down here....


I am unsure of what is going on here. You create a variable called "retval" which I assume is short for "Retrieve Values".
Is this an array or are we creating an object?

Code:

var retval =
    {
        'checkbox': 0,
        'radio':    0,
        'total':    0
    };



Are we passing "document.getElementsByTagName" to this conditional and if it doesn't exist we return nothing??

Code:

/* Browser does not support getElementsByTagName, return void */
    if(!document.getElementsByTagName)
    {
        return(retval);
    }


Here we get all the of the input tags, then count them and assign the count to retval.total
Code:

var elements = document.getElementsByTagName('input');
retval.total = elements.length;

return void, if no total from document.getElementsByTagName('input') return nothing?
Code:

/* No input tags in tree */
    if(!retval.total)
    {
        return(retval);
    }

declare "n" var and set to 0. If less than the total number of input elements, keep looping. Using the PRE-increment operator. Set all of the elements to lowercase to support all browser types with toLowerCase().
You then find the element type with: elements[n].type.
The [n] is just the increment for each type of element.

I know that this "The ++retval[]" is PRE-incrementing the element value and then returning it to the function (retval), but can someone explain to my how it works exactly?
The format just looks foreign to me...

Code:

    for(var n = 0; n < retval.total; ++n)
    {
       
      ++retval[elements[n].type.toLowerCase()];
    }

    return(retval);


let me know if I got most of the code right?

Thanks!

Salathe 04-22-2009 10:24 PM

Quote:

Originally Posted by allworknoplay (Post 23327)
I am unsure of what is going on here. You create a variable called "retval" which I assume is short for "Retrieve Values".

Only Kalle really knows, but I'd assume something like "return value(s)".
Quote:

Originally Posted by allworknoplay (Post 23327)
Is this an array or are we creating an object?
Code:

var retval =
    {
        'checkbox': 0,
        'radio':    0,
        'total':    0
    };


It's an 'object literal', a convenient way of creating a new object with some properties. Remember everything in JS is an object. The boring way of doing the same would be:
JavaScript Code:
var retval = new Object();
retval.checkbox = 0;
retval.radio    = 0;
retval.total    = 0


Quote:

Originally Posted by allworknoplay (Post 23327)
Are we passing "document.getElementsByTagName" to this conditional and if it doesn't exist we return nothing??
Code:

/* Browser does not support getElementsByTagName, return void */
    if(!document.getElementsByTagName)
    {
        return(retval);
    }


Basically, the condition asks if "document.getElementsByTagName" evaluates to boolean false. Since we're talking about a function, the condition will be false if it does not exist.

Also, it returns the retval object that was just created (with all zero values, remember) rather than void.

Quote:

Originally Posted by allworknoplay (Post 23327)
Here we get all the of the input tags, then count them and assign the count to retval.total
Code:

var elements = document.getElementsByTagName('input');
retval.total = elements.length;

return void, if no total from document.getElementsByTagName('input') return nothing?
Code:

/* No input tags in tree */
    if(!retval.total)
    {
        return(retval);
    }


Yep, you got it. (Again, not really void but the object with zero totals) :-)

Quote:

Originally Posted by allworknoplay (Post 23327)
I know that this "The ++retval[]" is PRE-incrementing the element value and then returning it to the function (retval), but can someone explain to my how it works exactly?
The format just looks foreign to me...
Code:

    for(var n = 0; n < retval.total; ++n)
    {
       
      ++retval[elements[n].type.toLowerCase()];
    }

    return(retval);


elements[n].type.toLowercase() is processed as follows. Get the nth item in the elements array (ie, the current one that we want to work with). Then get its type property (which is a String object). Then call the toLowerCase() method on that type property (the method can be called on any string). So the result of that expression is "checkbox" or "radio".

Now, the ++retval[…] should make a little more sense. Say the current element is a radio button, we are asking: ++retval["radio"] or please increment the value of retval["radio"] which is just another way of writing retval.radio

Kalle 04-23-2009 12:22 AM

As for the "retval", then yes it stands for "return value" and Salathe covered all the points I see ;)

allworknoplay 04-23-2009 12:23 AM

Thanks Salathe for explaining it to me in layman's terms.

I'll look into the object literal, that doesn't look like it's something that is available in PHP right?
Sounds pretty cool though, almost like a shortcut to using objects...

On your last explanation:

++retval[…]


Would that be considered a unary operator?


Also, when evaluating conditions like this:


Code:

if(!retval.total)
    {
        return(retval);
    }

Why must one return (retval)? Could we just do "nothing"?

Like this:


Code:

if(!retval.total)
    {
        return false;
    }


allworknoplay 04-23-2009 12:25 AM

Quote:

Originally Posted by Kalle (Post 23334)
As for the "retval", then yes it stands for "return value" and Salathe covered all the points I see ;)


Do you remember how long it took for you to get a good solid understanding of JS?

Was it 1 month? 6 months? a full year?

Kalle 04-23-2009 12:27 AM

You can return nothing like there, but! That means the render function will generate an error unless modified, but in that condition it would be wrong to change, as no inputs were found. Only the "if-browser-does-not-support-getElementsByTagName" you should return void and then check for void return in the Render function.

As for the "object literal" or closure object, its one of the things I would really like with real closures now in PHP 5.3, but lets hope they can be in 6.0 if someone makes a patch for it :)

Kalle 04-23-2009 12:29 AM

Quote:

Originally Posted by allworknoplay (Post 23336)
Do you remember how long it took for you to get a good solid understanding of JS?

Was it 1 month? 6 months? a full year?

hmm I don't know, I never really took time to learn it, I just did parts I needed to create for my projects so it's been all over the time while I've done frontend ;)

allworknoplay 04-23-2009 12:37 AM

Quote:

Originally Posted by Kalle (Post 23337)
You can return nothing like there, but! That means the render function will generate an error unless modified, but in that condition it would be wrong to change, as no inputs were found. Only the "if-browser-does-not-support-getElementsByTagName" you should return void and then check for void return in the Render function.

Yeahhhh.....I'll have to revisit this part because I have no idea what any of this means. :-(:-(


Quote:

Originally Posted by Kalle (Post 23337)
As for the "object literal" or closure object, its one of the things I would really like with real closures now in PHP 5.3, but lets hope they can be in 6.0 if someone makes a patch for it :)

You have a PHP.net account! You can make it happen!!

Salathe 04-23-2009 09:39 AM

Quote:

Originally Posted by allworknoplay (Post 23335)
I'll look into the object literal, that doesn't look like it's something that is available in PHP right?
Sounds pretty cool though, almost like a shortcut to using objects...

No, as Kalle said, object literals are not in PHP (yet). The closest thing, visually, that I can think of would be:

PHP Code:

$retval = (object) array(
  
'checkbox' => 0,
  
'radio'    => 0,
  
'total'    => 0
);

++
$retval->total;
print_r($retval); 

The ArrayObject (in PHP) would also allow the object- and array-syntaxes to be used ($retval->total and $retval['total']) if you wanted/needed them both.

Quote:

Originally Posted by allworknoplay (Post 23335)
On your last explanation:

++retval[…]


Would that be considered a unary operator?

Yep, because the operator acts on only one variable, it is a unary operation.

Quote:

Originally Posted by allworknoplay (Post 23339)
You have a PHP.net account! You can make it happen!!

PHP is an open source project, meaning anyone is free to contribute. A php.net account is not required! ^^

Kalle 04-23-2009 10:17 AM

Quote:

Originally Posted by Salathe (Post 23349)
No, as Kalle said, object literals are not in PHP (yet). The closest thing, visually, that I can think of would be:

PHP Code:

$retval = (object) array(
  
'checkbox' => 0,
  
'radio'    => 0,
  
'total'    => 0
);

++
$retval->total;
print_r($retval); 

The ArrayObject (in PHP) would also allow the object- and array-syntaxes to be used ($retval->total and $retval['total']) if you wanted/needed them both.


Yep, because the operator acts on only one variable, it is a unary operation.


PHP is an open source project, meaning anyone is free to contribute. A php.net account is not required! ^^

Exactly (about the last part), however I do have commit access to php-src, but my skills digging into ZE is abit too poor, but the API is pretty straight forward ;)

As for the ArrayObject, any class that implements the ArrayAccess interface should be able to be accessed like arrays and objects :)

allworknoplay 04-23-2009 05:28 PM

Hey guys, quick question, this goes a little back when Salathe suggested to use onLoad in the Body tag...

Here's what I currently have and it works...

shortened code:

Code:

<body>
<div><input type="checkbox" name="checkbox" value="checkbox" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox"  /></div>
<div><input type="checkbox" name="checkbox" value="checkbox"  /></div>
<div><input type="radio" name="radio"  /></div>
<div><input type="radio" name="radio"  /></div>
<div><input type="radio" name="radio"  /></div>

<script type="text/javascript">
<!--
showCount();
// -->
</script>

</body>

I move the function to be an onLoad event in the BODY tag and it works too...is this considered best practice?

Code:

<body onLoad="showCount();">
<div><input type="checkbox" name="checkbox" value="checkbox" /></div>
<div><input type="checkbox" name="checkbox" value="checkbox"  /></div>
<div><input type="checkbox" name="checkbox" value="checkbox"  /></div>
<div><input type="radio" name="radio"  /></div>
<div><input type="radio" name="radio"  /></div>
<div><input type="radio" name="radio"  /></div>

</body>


allworknoplay 04-23-2009 05:32 PM

Quote:

Originally Posted by Kalle (Post 23350)
Exactly (about the last part), however I do have commit access to php-src, but my skills digging into ZE is abit too poor, but the API is pretty straight forward ;)

As for the ArrayObject, any class that implements the ArrayAccess interface should be able to be accessed like arrays and objects :)

Speaking of contributing to PHP...

So I now learned that in JS you don't have to do backward slashes if you use double quotes.


var test = "today's a great day";


But in PHP you do...

$test = "today\'s a great day";

Unless you use single quotes in JS, then you would have to use backslash too...

Do you know if PHP is going to do something like this in the future so we don't have to use backslash if using double quotes?


All times are GMT. The time now is 05:29 AM.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0