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.
// pass 1 you have three sets of information, the difference is the
// div which has the listener, and the default data. (I've taken the liberty to
// make all of the names consistent.
$('#navninfoDiv').click(function() {
// based on your HTML, I believe that the input# is superfluous
$('#webhost_navninfo').data('myData', null);
});
$('#navninfoDivP').click(function() {
$('#webhost_navninfo').data('myData', 'p');
});
$('navninfoDivV').click(function() {
$('#webhost_navninfo').data('myData', 'V');
});
$('#prisinfoDiv').click(function() {
$('#webhost_prisinfo').data('myData2', null);
});
/* ... */
$('#cableinfoDiv').click(function() {
$('#webhost_cableinfo').data('myData3', null);
});
/* ... */
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:
var defaults = [null, "P", "V"]
for( var i = 0; i < defaults.length; i++ )
{
var divID = '#navninfoDiv' + ( defaults[i]?defaults[i]:"" );
$(divID).click(function() {
$('#webhost_navninfo').data('myData', defaults[i]);
});
}
for( i = 0; i < defaults.length; i++ )
{
var divID = '#prisinfoDiv' + ( defaults[i]?defaults[i]:"" );
$(divID).click(function() {
$('#webhost_prisinfo').data('myData2', defaults[i]);
});
}
for( i = 0; i < defaults.length; i++ )
{
var divID = '#cableinfoDiv' + ( defaults[i]?defaults[i]:"" );
$(divID).click(function() {
$('#webhost_cableinfo').data('myData3', defaults[i]);
});
}
Based on that, it looks like we have some repeaded code still, what if we looped over the divs' ID's too?
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
var defaults = [null, "P", "V"]
for( var j = 0; j < baseIDs.length; j++ )
{
for( var i = 0; i < defaults.length; i++ )
{
var divID = '#'+baseIDs[j]+'Div' + ( defaults[i]?defaults[i]:"" );
$(divID).click(function() {
var dat = i? 'myData': 'myData' + String( i + 1 );
$('#webhost_'+baseIDs[j]).data(dat, defaults[i]);
});
}
}
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:
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
var defaults = [null, "P", "V"]
for( var j = 0; j < baseIDs.length; j++ )
{
for( var i = 0; i < defaults.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
assignClickListener(baseIDs[j], defaults[i], datLab);
}
}
function assignClickListener(base, defaults, datLab)
{
var divID = '#'+base+'Div' + ( defaults?defaults:"" );
$(divID).click(function() {
$('#webhost_'+base).data(datLab, defaults);
});
}
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.
// I'm going to omit this until we re-unite all of the code at the end.
$('#smt').click(function() {
// so you have the same looping structure here:
var myData = $('#webhost_navninfo').data('myData'),
val = $('#webhost_navninfo').val();
if (myData) {
$('#webhost_navninfo').val(myData + val);
}
var myData2 = $('#webhost_prisinfo').data('myData2'),
/* ... */
var myData3 = $('#webhost_cableinfo').data('myData3'),
val3 = $('#webhost_cableinfo').val();
if (myData3) {
// this looks like a mistake. I will assume that it is supposed
// to be webhost_cableinfo.
$('#webhost_navninfo').val(myData3 + val3);
}
});
Well, since the loop worked so well last time, why don't we try to do the same thing again?
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
for( var i = 0; i < baseIDs.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
var currentBase = baseIDs[i];
var myData = $('#webhost_'+currentBase).data(datLab),
val = $('#webhost_'+ currentBase).val();
if (myData) {
$('#webhost_' + currentBase).val(myData + val);
}
}
Whoops. Looks like I missed somethign there -- I could re-use that ID:
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
for( var i = 0; i < baseIDs.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
// since this is actually the ID now, I've renamed the variable.
var currentID = '#webhost_'+baseIDs[i];
var myData = $(currentID).data(datLab),
val = $(currentID).val();
if (myData) {
$(currentID).val(myData + val);
}
}
Hmmm... I bet I could cache even more of that:
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
for( var i = 0; i < baseIDs.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
// I can actually cache this entire element. I'll do that:
var currentElem = $('#webhost_'+baseIDs[i]);
var myData = currentElem.data(datLab),
// val = currentElem.val(); <!-- I don't need this value, I'll just
// calculate it inline.
if (myData) {
currentElem.val(myData + currentElem.val());
}
}
Ok, now we're ready to combine both and see how we've done:
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
var defaults = [null, "P", "V"]
for( var j = 0; j < baseIDs.length; j++ )
{
for( var i = 0; i < defaults.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
assignClickListener(baseIDs[j], defaults[i], datLab);
}
}
function assignClickListener(base, defaults, datLab)
{
var divID = '#'+base+'Div' + ( defaults?defaults:"" );
$(divID).click(function() {
$('#webhost_'+base).data(datLab, defaults);
});
}
for( i = 0; i < baseIDs.length; i++ )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
var currentElem = $('#webhost_'+baseIDs[i]);
var myData = currentElem.data(datLab),
if (myData) {
currentElem.val(myData + currentElem.val());
}
}
Notice the bug? Notice places to remove duplicate code?
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
var defaults = [null, "P", "V"]
for( var j = 0; j < baseIDs.length; j++ )
{
for( var i = 0; i < defaults.length; i++ )
{
/*
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
I really don't like this pattern. I repeat it twice. We can fix that
*/
assignClickListener(baseIDs[j], defaults[i], getDataLabel(j));
}
}
// I left this part out. That's the bug.
$('#smt').click(function() {
// make i local here. Otherwise it could be destructive
for( var i = 0; i < baseIDs.length; i++ )
{
var currentElem = $('#webhost_'+baseIDs[i]);
var myData = currentElem.data(getDataLabel( i )),
if (myData) {
currentElem.val(myData + currentElem.val());
}
}
}
function assignClickListener(base, defaultData, datLab)
{
var divID = '#'+base+'Div' + ( defaultData?defaultData:"" );
$(divID).click(function() {
$('#webhost_'+base).data(datLab, defaultData);
});
}
function getDataLabel( i )
{
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
return datLab;
}
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:
var baseIDs = [ 'navninfo', 'prisinfo', 'cableinfo' ];
var defaults = [null, "P", "V"]
for( var j = 0; j < baseIDs.length; j++ ) {
for( var i = 0; i < defaults.length; i++ ) {
assignClickListener(baseIDs[j], defaults[i], getDataLabel(j));
}
}
$('#smt').click(function() {
for( var i = 0; i < baseIDs.length; i++ ) {
var currentElem = getHostElement(baseIDs[i]);
var myData = currentElem.data(getDataLabel( i )),
if (myData) {
currentElem.val(myData + currentElem.val());
}
}
} ); // note: this was a bug in previous iteration. I missed the );
function assignClickListener(base, defaultData, datLab) {
var divID = '#'+base+'Div' + ( defaultData?defaultData:"" );
$(divID).click(function() {
getHostElement(base).data(datLab, defaultData);
});
}
var elementCache = {}
function getHostElement( baseLab ) {
if( !elementCache[ baseLab ] )
elementCache[ baseLab ] = $('#webhost_'+baseLab);
return elementCache[ baseLab ];
}
function getDataLabel( i ) {
var datLab = 'myData'
if( i ) datLab += String( i + 1 );
return datLab;
}
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.