1

Let´s say I want to have 10-20 of the following div´s. How can I merge the jQuery code into one bit, so that I don´t have to copy it?

<div class="one">
    <h2>Test</h2>
</div>

<div class="one_new">
    <h2>Test</h2>
</div>

<div class="two">
    <h2>Test</h2>
</div>

<div class="two_new">
    <h2>Test</h2>
</div>

$(function() {
    $('.one').click(function() {
    $('.one').css( "display", "none")
    $('.one_new').css( "display", "table");
  });
});

$(function() {
    $('.two').click(function() {
    $('.two').css( "display", "none")
    $('.two_new').css( "display", "table");
  });
});

UPDATE: https://jsfiddle.net/d9x45nyd/12/

4
  • Do they have any common properties? exclude they're all <div>? Commented Jul 12, 2015 at 9:54
  • Well, 1 and 3 has the same bg_color; 2 and 4 another bg_color; and so on... I just want to change the h2 on click... Commented Jul 12, 2015 at 9:59
  • Is the html fixed, or can you change it? You can add a second class to all of the divs, like so: <div class="one clickme">Click Me!</div><div class="two clickme">Click me too!</div> Commented Jul 12, 2015 at 10:31
  • Here is the jsfiddle.net/d9x45nyd/12 to my question... Commented Jul 12, 2015 at 11:37

3 Answers 3

1

The basic problem you want to solve is how to relate elements (divs in your case) so that when one is clicked, a related one is shown and the original element is hidden.

There are a number of ways to do this:

  • based on the hierarchy (i.e. find the next div)
  • arrays of selectors (hard to maintain with the HTML)
  • one handler per item (your original, but that does not scale well)

My personal suggestion, in most situations like this, is to "data-drive" the HTML. That is, the HTML is authored to contain enough meta data to allow decisions to be made by relatively simple code. This puts all the maintenance, e.g. for new elements, together with the elements themselves.

One easy way to data-drive is to use data- attributes on the elements e.g. to hold selectors for their related elements.

e.g. this is an explanatory example (so is not the minimum code required):

HTML:

<div class="one" data-target=".one_new">
     <h2>Test one</h2>
</div>
<div class="one_new" style="display:none;">
     <h2>Test one new</h2>
</div>
<div class="two" data-target=".two_new">
     <h2>Test two</h2>
</div>
<div class="two_new" style="display:none;">
     <h2>Test two new</h2>
</div>

jQuery

$(document).on('click', 'div', function () {
    // Only bother to wrap this once - common practice
    var $this = $(this);
    // Get the data-target element from the div clicked
    var target = $this.data('target');
    // If it has a target...
    if (target) {
        // use it as a jQuery selector to select the matching div 
        $(target).css('display', 'table');
        $this.hide();
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/mkLqvrrm/2/

This method uses a single delegated event handler, attached to a non-changing ancestor element. document is the best default if nothing else is closer/convenient. It works by listening for the event (i.e. click) to bubble up to the ancestor. It then applies a jQuery selector to the elements in the bubble chain only. It then applies the function to only the matching elements that caused the event.

This method is very efficient to connect and the runtime overhead, at event time, is negligible (as you can't click the mouse fast enough to notice any difference compared to a directly connected event handler).

Sign up to request clarification or add additional context in comments.

1 Comment

@codemaniac: The code can be shortened a little more, but I wanted you to see the principals clearly. If you are happy with this approach, mark as answer when you can.
0

You can try code like :

$(function() {
    $('div').click(function() {
    var classAttr = $(this).attr('class');
    $('.'+classAttr).css( "display", "none")
    $('.'+classAttr +'_new').css( "display", "table");
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="one">
    <h2>Test</h2>
</div>

<div class="one_new"  style="display:none">
    <h2>Test one_new</h2>
</div>

<div class="two">
    <h2>Test</h2>
</div>

<div class="two_new" style="display:none">
    <h2>Test two_new</h2>
</div>

2 Comments

This answer is correct. You need to use something all the items have in common so jQuery can find them. The div tag is not a good candidate for this in any real life example, since it probably used a lot of other places on the page. The most common case is to use a class name.
One problem with this method is maintenance, as it assumes only one class is present. If a new class is added anywhere, e.g. for styling, it will stop working.
0

Create a function that takes a selector as an argument and creates a click handler, like so:

function attachClickHandler(selector) {
    $(selector).click(function() {
        $(this).css('display', 'none');
        $(selector + '_new').css('display', 'table');
    });
}

var selectors = ['.one', '.two'];
for(var i = 0; i < selectors.length; i++) {
    attachClickHandler(selectors[i]);
}

There are many other solutions to this problem, but this is the most simple example of factorising the desired jQuery functionality.

6 Comments

You meant "refactoring", not "factorising", but this solution is more complicated than needed for the simple task of relating elements. Better off data-driving the selection using data- attributes.
Yes, I do -- thanks! I disagree however that it is more simple to introduce custom data attributes as a solution in this instance.
Using a single delegated handler, with data to drive selection, is always preferable to using handlers connected in a loop. It is also easier to maintain as the attributes are with the elements and not in an array elsewhere
I agree. However, I believe that for the purposes of this question (which is what I mean by 'in this instance') it is likely easier for the OP to understand my answer than it is to introduce the concepts you have mentioned. Your theoretical solution is in my opinion beyond the reach of OP's question How can I merge the jquery code into one bit, so that i don´t have to copy it?. If you think otherwise, post an answer!
Now I am back to a real keyboard, I have added my own suggestions with example. You should now see how simple the approach actually is and how easy it is to add new items. IMHO (based on decades of programming) maintenance of the page should be a key concern for everyone up-front :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.