Event Handlers... Toggling a Numeric Field

G

GregR

So, you've all probably seen interfaces with a numeric field and
little up and down arrows to the right of the field to toggle the
numbers up and down. I'm trying to make one of those in Javascript
and HTML.

I have one working, but I'm using the "older" inline event handlers.
Basically, in the html, I have:

onclick="toggleUp( 'fieldId', toggleValue)" and
onclick="toggleDown( 'fieldId', toggleValue)"

....on the up and down arrow images respectively. I have an "Almost"
generic function that accepts these values and does the given
increment up or down. Works fine. Toggles the field, the other
dependant fields update as they should.

Problem 1.)
Now, I want to get the event handlers out of the HTML. I've not been
JS'ng long, and I've been reading up on event listeners and such and
I'm still a little fuzzy on how to just switch this code from inline
event handlers to event listeners that lie only in the JS file. It
needs to be pretty generic so that I can reuse it since I have several
different "forms" on different pages with these toggle fields, and
each form has at least 4 of these toggled fields on it.

So, how can I make a generic event handler that will listen for an
onclick on one of these images and know, 1. Which arrow was clicked
and 2. what field is associated with that arrow (up or down) so that
the correct field is incremented (up or down). Do I need an
differend listener for each field/arrow combo? Four fields, each
having two arrows = 8 event listeners? Or can I do it more
generically than that?

Problem 2.)
I also want to have the toggleUp() and toggleDown() functions generic
enough to work on any form. Right now, within each of these toggle
functions on the page I have working I include it to trigger the
function to recalculate all the fields when the toggleUp() is
triggered. For example:

function toggleUp(id,incr) {
var field = document.getElementById(id);
document.getElementById(id).focus();
var curValue = +(field.value);
var newValue = curValue + incr;
document.getElementById(id).value = newValue.toFixed(1);
recalcFormNameFields();
}

For the toggle function to be re-usable among forms, I need to get
that recalcForm4Fields() function call out of there, since each form
uses very different fields and equations. How can I trigger the
"correct" recalc function without putting it in the toggleUp()/
toggleDown() function itself?

Forgive me if these are basic questions. I've been a designer for
years and just started learning JS a few months ago...

Thanks for any input!!!

Greg
 
P

Peter Michaux

So, you've all probably seen interfaces with a numeric field and
little up and down arrows to the right of the field to toggle the
numbers up and down. I'm trying to make one of those in Javascript
and HTML.

I have one working, but I'm using the "older" inline event handlers.
Basically, in the html, I have:

onclick="toggleUp( 'fieldId', toggleValue)" and
onclick="toggleDown( 'fieldId', toggleValue)"

What is toggleValue? A global variable?
...on the up and down arrow images respectively. I have an "Almost"
generic function that accepts these values and does the given
increment up or down. Works fine. Toggles the field, the other
dependant fields update as they should.

This seems like a good approach for a simple problem like you have.

Problem 1.)

Who told you this was a problem? ;-)
Now, I want to get the event handlers out of the HTML. I've not been
JS'ng long, and I've been reading up on event listeners and such and
I'm still a little fuzzy on how to just switch this code from inline
event handlers to event listeners that lie only in the JS file.

This is getting into tricky territory for a few reasons. No matter
what the solution is, if the JavaScript is completely outside the HTML
then the solution will be far more complex and introduce problems of
its own. There may be advantages but without seeing a more complete
example it is difficult to know for sure that the advantages are worth
the extra pain.

Part of the problem also comes from Internet Explorer's event model
not matching the DOM standard that most other mainstream browsers like
FireFox, Opera, Safari use. So the event library code that needs to be
written in JavaScript will probably wrap the various browser event
interfaces so your application code (i.e. stuff related to toggleUp
and your particular HTML) will be easier to write.

Another problem is you will need to attach event handler functions to
some element(s) in the page so you can react when the user clicks.
When you attach these listeners causes a problem. If you wait until
the page has been rendered (i.e. the window.onload event fires) then
you may be too late. The user may have clicked one of the toggle
images before you were able to attach the listener to that toggle
element.

You could use a delegate click listener on the window object. This is
non-standard but allows you to add a listener before the page body
begins to render. That is, you won't attach your click listener too
late. The delegate listener would receive the click event after it
bubbles up through the DOM ancestors from the element the user
clicked. When it arrives at the delegate listener that listener can
determine what was clicked and the appropriate action to take.

You can see there are many subtitles introduced by adding the
restriction that "inline event handlers are bad." They aren't really
bad. They are simple and they work. You have extracted the majority of
the functionality out of the HTML and that code can be put in a
separate JavaScript file. That helps with caching issues.
It
needs to be pretty generic so that I can reuse it since I have several
different "forms" on different pages with these toggle fields, and
each form has at least 4 of these toggled fields on it.

That shouldn't be a problem.
So, how can I make a generic event handler that will listen for an
onclick on one of these images and know, 1.

Use a JavaScript library with an event module. The problem is no one
here will recommend any particular mainstream JavaScript library
because the quality of these libraries has been judged poor. This is
unfortunate because it would really help you in this situation.
Which arrow was clicked
and 2. what field is associated with that arrow (up or down) so that
the correct field is incremented (up or down).

If you pick a library and study it a bit you will see how to do these
things.
Do I need an
differend listener for each field/arrow combo?

No you could use a delegate listener on an ancestor element. The form
element or the window element like I described above.
Four fields, each
having two arrows = 8 event listeners? Or can I do it more
generically than that?

There are many ways to do it.
Problem 2.)
I also want to have the toggleUp() and toggleDown() functions generic
enough to work on any form. Right now, within each of these toggle
functions on the page I have working I include it to trigger the
function to recalculate all the fields when the toggleUp() is
triggered. For example:

function toggleUp(id,incr) {
var field = document.getElementById(id);
document.getElementById(id).focus();

you already have done the document.getElementById(id) part so the line
above can be just

field.focus();
var curValue = +(field.value);

The addition symbol and parenthesis in the line above don't do
anything.
var newValue = curValue + incr;
document.getElementById(id).value = newValue.toFixed(1);

field.value = newValue.toFixed(1)
recalcFormNameFields();

}

For the toggle function to be re-usable among forms, I need to get
that recalcForm4Fields() function call out of there, since each form
uses very different fields and equations. How can I trigger the
"correct" recalc function without putting it in the toggleUp()/
toggleDown() function itself?

There are many ways you could do this. You can pass a function to
toggleUp as a third argument.

<script type="text/javascript">
function recalcOne() {
//...
}
function recalcTwo() {
//..
}

toggleUp(id, incr, recalcFun) {

// do stuff
//...
// last step call the recalcFun
recalcFun();
}

</script>

Then in the HTML

onclick="toggleUp('someId', toggleValue, recalcOne)"
....
onclick="toggleUp('someOtherId', toggleValue, recalcTwo)"

There are many ways to do this. You could build a particular function
for each type of toggle.

<script>
function someIdToggleUp() {
toggleUp('someId', incr, recalcOne)
}
function someOtherIdToggleUp() {
toggleUp('someOtherId', incr, recalcTwo)
}
</script>

This would clean up your inline handlers

onclick="someIdToggleUp();"
....
onclick="someOtherIdToggleUp()"

Forgive me if these are basic questions. I've been a designer for
years and just started learning JS a few months ago...

I hope you like JavaScript. It takes lots of time to learn it. I once
saw an "illegal" css zen garden design that had a little bit of
JavaScript to make some clouds move slowly across a nice blue sky.
Normally animations are annoying but a designer can make some tasteful
use of it.

Please see the following for more info

<URL: http://www.jibbering.com/faq/>
<URL: http://www.jibbering.com/faq/#FAQ3_1> + errata on O'Reilly site

Peter
 
G

GregR

onclick="toggleDown( 'fieldId', toggleValue)"
"What is toggleValue? A global variable? "

Sorry, toggleValue is the value to increment by when the up/down arrow
icon is clicked. In my case it usually looks like this:


onclick="toggleDown( 'fieldId', 0.1)"
 
G

GregR

This seems like a good approach for a simple problem like you have.


Who told you this was a problem? ;-)

Me! :-D
This is getting into tricky territory for a few reasons. No matter
what the solution is, if the JavaScript is completely outside the HTML
then the solution will be far more complex and introduce problems of
its own. There may be advantages but without seeing a more complete
example it is difficult to know for sure that the advantages are worth
the extra pain.


I'll get a sample up if I still have issues...

Use a JavaScript library with an event module. The problem is no one
here will recommend any particular mainstream JavaScript library
because the quality of these libraries has been judged poor. This is
unfortunate because it would really help you in this situation.


A friend suggested Prototype + LowPro (danwebb.net) to me...


you already have done the document.getElementById(id) part so the line
above can be just

field.focus();


Good catch! :) Thanks.

The addition symbol and parenthesis in the line above don't do
anything.


I was occassionally having problems doing math with the values from
some fields. It seemed they were being read as strings from the "text
fields" (suprise). Doing some researched, I found someone suggest
putting the +() around the field to force it to an integer. It solved
my problem, so...I kept using it as a safeguard.

field.value = newValue.toFixed(1)


There I go again... ;-)

There are many ways you could do this. You can pass a function to
toggleUp as a third argument.

<script type="text/javascript">
function recalcOne() {
//...
}
function recalcTwo() {
//..
}

toggleUp(id, incr, recalcFun) {

// do stuff
//...
// last step call the recalcFun
recalcFun();
}

</script>

Then in the HTML

onclick="toggleUp('someId', toggleValue, recalcOne)"
...
onclick="toggleUp('someOtherId', toggleValue, recalcTwo)"

There are many ways to do this. You could build a particular function
for each type of toggle.


Ok, makes sense...

<script>
function someIdToggleUp() {
toggleUp('someId', incr, recalcOne)
}
function someOtherIdToggleUp() {
toggleUp('someOtherId', incr, recalcTwo)
}
</script>

This would clean up your inline handlers

onclick="someIdToggleUp();"
...
onclick="someOtherIdToggleUp()"


Hmmm....I think I see what's going on there. Probably take a few
minutes to process. :p

I hope you like JavaScript. It takes lots of time to learn it. I once
saw an "illegal" css zen garden design that had a little bit of
JavaScript to make some clouds move slowly across a nice blue sky.
Normally animations are annoying but a designer can make some tasteful
use of it.



Thanks!
 
D

Dr J R Stockton

In comp.lang.javascript message <7e3f8c2b-f6a6-4c8f-8859-215a00f45869@41
g2000hsc.googlegroups.com>, Tue, 26 Feb 2008 21:09:09, Peter Michaux
The addition symbol and parenthesis in the line above don't do
anything.


Without the first quoted +, the second will concatenate, will it not?

OP: note that
document.getElementById('ID').value++
works (and probably should) though
document.getElementById('ID').value+=1
works differently.
 
D

David Mark

Me! :-D





I'll get a sample up if I still have issues...




A friend suggested Prototype + LowPro (danwebb.net) to me...

LOL. With friends like those...

1. Prototype is an abomination. Do not use it for anything, let alone
something as simple as this.

2. I have vaguely heard of LowPro, but it appears to have several
drawbacks. For one, it is an extension of Prototype. (!) For two,
the technical editor of that "Pro JavaScript Techniques" book by the
jQuery guy is named Dan Webb. (!!) I have also heard that guy writes
JS for Google. That should be enough to put you off any JavaScript
from a domain called danwebb.net.

[snip]
 
G

GregR

In comp.lang.javascript message <7e3f8c2b-f6a6-4c8f-8859-215a00f45869@41
g2000hsc.googlegroups.com>, Tue, 26 Feb 2008 21:09:09, Peter Michaux
<[email protected]> posted:





Without the first quoted +, the second will concatenate, will it not?


Yes, that's why I did +(field.value). Otherwise JS was trying to
concat the two and I'd get "NaN" in the answer field.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top