How do I make this Jquery dry?
// Adding data to input depending on what div is clicked
$('#navninfoDiv').click(function() {
$('input#webhost_navninfo').data('myData', null);
});
$('#navninfoDivP').click(function() {
$('input#webhost_navninfo').data('myData', 'p');
});
$('navninfoDivV').click(function() {
$('#inputwebhost_navninfo').data('myData', 'V');
});
// Adding data to input depending on what div is clicked
$('#prisinfoDiv').click(function() {
$('#inputwebhost_prisinfo').data('myData2', null);
});
$('#prisinfoDivP').click(function() {
$('#inputwebhost_prisinfo').data('myData2', 'p');
});
$('#prisinfoDivV').click(function() {
$('#inputwebhost_prisinfo').data('myData2', 'V');
});
// Adding data to input depending on what div is clicked
$('#cableinfoDiv').click(function() {
$('#inputwebhost_cableinfo').data('myData3', null);
});
$('#cableinfoDivP').click(function() {
$('#inputwebhost_cableinfo').data('myData3', 'p');
});
$('#prisinfoDivV').click(function() {
$('#inputwebhost_cableinfo').data('myData3', 'V');
});
// Adding data to input on submit
$('#smt').click(function() {
// for input#webhost_navninfo
var myData = $('#webhost_navninfo').data('myData'),
val = $('#webhost_navninfo').val();
if (myData) {
$('#webhost_navninfo').val(myData + val);
}
// for input#webhost_prisinfo
var myData2 = $('#webhost_prisinfo').data('myData2'),
val2 = $('#webhost_prisinfo').val();
if (myData2) {
$('#webhost_prisinfo').val(myData2 + val2);
}
// for input#webhost_cableinfo
var myData3 = $('#webhost_cableinfo').data('myData3'),
val3 = $('#webhost_cableinfo').val();
if (myData3) {
$('#webhost_navninfo').val(myData3 + val3);
}
});
How do I dry all this code up? I have many more input fields about 50.
Here is my HTML and jQuery without the data functions: http://jsfiddle.net/z5qeX/2/
The code example I gave in this example is just to illustrate the functionality I want. It does not match the HTML in the jsfiddle, but it is the code I want to add it to later.
This is a sytematic refinement of the code which you provided. There are alternate solutions (like ShankarSangoli's) which provide you with good alternatives that require modifications to the HTML, but this should work with exactly what you have right now.
This is going to be done in multiple passes so I can explain what is going on.
Since you're using a naming convention, it is actually pretty simply to loop that. First we'll place the "data" part in a loop:
Based on that, it looks like we have some repeaded code still, what if we looped over the divs' ID's too?
That doesn't look very clean. I bet it wouldn't be hard to take all of that center stuff and put it into its own little function which would make it far easier to debug and a lot cleaner:
So, now we've finished the first part of the script. Let's see if there is a similar way to look at the second part of your script.
Well, since the loop worked so well last time, why don't we try to do the same thing again?
Whoops. Looks like I missed somethign there -- I could re-use that ID:
Hmmm... I bet I could cache even more of that:
Ok, now we're ready to combine both and see how we've done:
Notice the bug? Notice places to remove duplicate code?
I can see one last thing which can be removed easily. We keep looking up
$('#webhost_<id>')
. What if that needs to change? No, I think we should move that out as well. While we're at it, we might as well cache it:Now, the result is only about 50% fewer lines of code and it is far easier to test and because it has less direct repetition, each piece of this code is easier to understand.
It's a good idea to only define all those literals once.
Doing the same with DOM element references spares jQuery from identifying the element again and again. So it also runs faster.
You could try:
and do something similar for the rest of it. In the $("#smt").click bit.
Below is a first pass. I'm not sure how far you want to take this, but as arunkumar points out, it could all be data-driven.
A few questions that might help:
What follows is smaller code. It can certainly be dried up more (a function that creates the click handler anyone?), but without understanding the context a bit, I'm hesitant to do so:
Your code seemed to have some inconsistencies, so I made a few assumptions. For example, I'm not sure if you always meant
$('input#webhost_navninfo')
or$('#inputwebhost_navninfo')
.If you don't care about how
myData
is numbered so long as the information is all associated correctly, then you could get rid of the variabledataIndex
and just useindex
in both cases.The idea here is to have minimal changes to the markup as well as achieve the goals with minimal code.
Assuming that you have markup like:
I rearranged it within a container div to:
.delegate()
HTML:
JS:
Click for Live Demo !
Tried to keep it simple and readable and made all those assumptions. I hope this sets you up in the right direction.
I like Shankar's answer too simply because of use of data attributes. However, I don't like those pesky selectors. Plus too many calls to
.data
bag which is a overhead I tried to avoid.