views:

3976

answers:

4

I've been searching around this morning and I'm not finding any simple solutions... basically, I want to capture a change in an input element, but also know the previous value.

Here's a change event and an input element in its simplest form. Clearly, I can get the new value with $(elem).val(), but is there a sneaky method I'm missing for getting the previous value? I don't see anything in the jQuery API to do this, but maybe someone's already done this and has some tips?

<script>
    $(document).ready(function(){
        $('#myInputElement').bind('change', function(){
            //var oldvalue = ???
            var newvalue = $(this).val();
        });
    });
</script>
<input id="myInputElement" type="text">

I'm not against writing my own solution, I just want to make sure I'm not recreating the wheel here.

+5  A: 

you could store the previous value in a global variable e.g.

<script>
    var oldValue;

    $(document).ready(function(){
        // Get the initial value
        oldValue = $('#myInputElement').val();

        $('#myInputElement')
            .change(function(){
                var newvalue = $(this).val();
            })
            .focus(function(){
                // Get the value when input gains focus
                oldValue = $(this).val();
            })
    });
</script>
<input id="myInputElement" type="text">
Russ Cam
Yeah, this works similarly to the idea I posted as a comment below. My form submits through a web service, so it's possible that a user will make changes, save the form, and make more changes. I'll need to manage those previous values throughout the life of the form. I think the focus event I mentioned below may help with updating those global variables.
SeanW
Yep, this works perfectly... and I either missed that you put focus in there, or you edited it afterward... haha... either way, it does exactly what I need it to do. Thanks!
SeanW
I must have been editing while you were commenting :) You could go one step further and store all the old values in an array and have an option more than just the latest old value. Just a thought...
Russ Cam
Funny you mention that, that's exactly what I'm doing now... I'm still not exactly sure how I want to store the previous values, I just know now that I can do it. I may store all changes, or just the previous 'saved' values... thanks a bunch!
SeanW
global vars...yak
redsquare
+1  A: 

You could have the value of the input field copied to a hidden field whenever focus leaves the input field (which should do what you want). See code below:

<script>
    $(document).ready(function(){
        $('#myInputElement').bind('change', function(){
            var newvalue = $(this).val();
        });
        $('#myInputElement').blur(function(){
            $('#myHiddenInput').val($(this).val());
        });
    });
</script>
<input id="myInputElement" type="text">

(untested, but it should work).

inkedmn
This isn't a bad idea... I'll have to test. I wonder if the bind and blur events fire in the same order every time... if so, that may work. Alternatively, I may be able to use the focus event so that when an element is focused, I store the value. Then on change, I have the old and new values... I'll do some testing and see what I can come up with.
SeanW
I did some testing and the focus method works brilliantly. Thanks to both of you for the ideas/samples!
SeanW
A: 

In Russ answer he binds the focus event. I don't think it is necessary.

You can store the old value in the change event.

<script>
    $(document).ready(function(){

        var newValue = $('#myInputElement').val();
        var oldValue;

        $('#myInputElement').change(function(){
            oldValue = newValue;
            newValue = $(this).val();
        });
    });
</script>
<input id="myInputElement" type="text">
Daniel Moura
Daniel, the problem with this is that you only get the old value once. Because my form submits through a webservice (ajax), the document only loads once, but the form values can change N number of times. By using the focus method, I'm guaranteed to pick up the new input value.
SeanW
Oh, actually - I see what you're doing... my mistake. Yeah, this would work too.
SeanW
+7  A: 

A better approach is to store the old value using .data. This spares the creation of a global var which you should stay away from and keeps the information encapsulated within the element. A real world example as to why Global Vars are bad is documented here

e.g

<script>
    //look no global needed:)

    $(document).ready(function(){
        // Get the initial value
       var $el = $('#myInputElement');
       $el.data('oldVal',  $el.val() );


       $el.change(function(){
            //store new value
            var $this = $(this);
            var newValue = $this.data('newVal', $this.val());
       })
       .focus(function(){
            // Get the value when input gains focus
            var oldValue = $(this).data('oldVal');
       });
    });
</script>
<input id="myInputElement" type="text">
redsquare
I learn something new every day about jQuery... this is the first I've seen of .data() so I'll definitely read more about it today.
SeanW
@redsquare - totally forgot about .data() - nice!
Russ Cam
@redsquare: I didn't know about .data. Very nice :)
Daniel Moura
Wow... ok, thank you, thank you, thank you for turning me on to .data()!!! I just got done reading up on this, and this will change my application to be MUCH more manageable. Gone are my custom, very invalid, attributes storing data.Ok, now what's the proper StackOverflow etiquette here - I've already marked an answer, but there's an even better one now... do I mark this one?
SeanW
redsquare
Makes sense. I would definitely look for the best answer. Thanks for your help!
SeanW
no problem Sean, anytime
redsquare
IMO, only inexperienced programmers are going to have problems with global variables.
Josh Stodola
Not true, even MS render global vars in there ms ajax scripts that can catch people out when they happen to name their control the same as the global var. Def not an inexperienced only problem
redsquare
@redsquare: This is great but looks like some logic isn't quite right. `.data('oldVal')` is only ever set when the page is loaded and never after. Probably in the `change` or `focus` event it should be something like `$(this).data('oldVal', $(this).val())`?
Alex Angas
@Alex-Angas, I took it that he wanted the previous value as in the value when the form was rendered to the screen, not after every change whilst on the screen as that makes no sense really
redsquare