Load div below row of containers - new click event

Hi all,

If you have a quick look at the fiddle you’ll see the working solution in action. Everything works ok, until I change the click event onto another element and looks like this.

What I need is to change the click event onto the more link as shown in the second fiddle. Only this causes the hidden div to display inside column__4 instead of outside.

I’m just not sure what I need to change so everything works as it does in the first example with the new click event.

js

$(document).on('click', '.column__4', function(e){
//this is what i need 
//$(document).on('click', '.more', function(e){

    $chosen = $(this);
    var n = $chosen.closest('div.column__4').find('span').attr("data-ref");
    console.log(n);

    $('#content').css('display','inline-block').text(n);
    var top = $(this).offset().top;
    var $blocks = $(this).nextAll('.column__4');
    if ($blocks.length == 0) {
        placeAfter($(this));
        return false;
    }
    $blocks.each(function(i, j) {
        if($(this).offset().top != top) {
            placeAfter($(this).prev('.column__4'));
            return false;
        } else if ((i + 1) == $blocks.length) {
            placeAfter($(this));
            return false;
        }
    });
      
   e.preventDefault();
});

Then uncomment and comment the click events to see my problem.

//$(document).on('click', '.column__4', function(e){
$(document).on('click', '.more', function(e){

html

<div class="column__4 col show">1
  <span class="more" data-ref="1">more</span>
</div>
<div class="column__4 col show">2
  <span class="more" data-ref="2">more</span>
</div>
<div class="column__4 col show">3
  <span class="more" data-ref="3">more</span>
</div>
<div class="column__4 col show">4
  <span class="more" data-ref="4">more</span>
</div>
<div class="column__4 col show">5
  <span class="more" data-ref="5">more</span>
</div>
<div class="column__4 col show">6
  <span class="more" data-ref="6">more</span>
</div>
<div class="column__4 col show">7
  <span class="more" data-ref="7">more</span>
</div>
<div class="column__4 col show">8
  <span class="more" data-ref="8">more</span>
</div>

<div id="content">
  content is king
</div>

For anybody involved with the [last thread] (Display content below full row - jQuery toggle) @m_hutley @PaulOB. I decided to use the code above. I’m now loading the content dynamically via json and one record is fetched on click each time.

Thanks, Barry

Update

I added .closest(".column__4") which solved the above issue using the new click event
$(document).on('click', '.more', function(e){}

if ($blocks.length == 0) {
    placeAfter($(this).closest(".column__4"));
    return false;
}

Halfway there :slight_smile:

Updated fiddle http://jsfiddle.net/9wv52d0j/6/

The final problem is how we place the Content div after the last column__4 in the row.

I think it’s something to do with calculating which block it needs to follow with the offset method.

var top = $(this).offset().top;
    var $blocks = $(this).nextAll('.column__4');
    if ($blocks.length == 0) {
        placeAfter($(this).closest(".column__4"));
        return false;
    }
    $blocks.each(function(i, j) {
        if($(this).offset().top != top) {
            placeAfter($(this).prev('.column__4'));
            return false;
        } else if ((i + 1) == $blocks.length) {
            placeAfter($(this));
            return false;
        }
    });

Thanks.

Any ideas?

Thanks.

Can anybody shed any light on this?
Updated fiddle http://jsfiddle.net/9wv52d0j/6/

Thanks,
Barry

Hi Barry,

If your not opposed to altering the html slightly I can offer a solution that meets your requirements. It uses your script from the last updated fiddle.

From what I see with your three divs on a row at 32% width, is that there will be no more than three divs per row. You can nest those three divs in a parent div and then target with .closest(".row")


<div class="row">
  <div class="column__4 col show">1
    <span class="more" data-ref="1">more</span>
  </div>
  <div class="column__4 col show">2
    <span class="more" data-ref="2">more</span>
  </div>
  <div class="column__4 col show">3
    <span class="more" data-ref="3">more</span>
  </div>
</div>

I used flexbox for the layout instead of floats but it will work with floats too.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Load div below row of containers - new click event</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>

<style>
.row {
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
  margin: 0 0 10px;
}
.column__4 {
  display: flex;
  flex: 0 1 33%;
  min-height: 200px;
  margin: 0 5px;
  padding: 10px;
  box-sizing: border-box;
  background: purple;
  color: white;
}
.more {
  margin-top: auto;
  margin-left: auto;
  padding: 5px;
  cursor: pointer;
}
#content {
  display: none;
  margin: 0 5px 10px;
  padding: 5px;
  text-align: center;
  background: #333;
  font-weight: 600;
  color: #fff;
}
</style>

</head>
<body>

<div class="row">
  <div class="column__4 col show">1
    <span class="more" data-ref="1">more</span>
  </div>
  <div class="column__4 col show">2
    <span class="more" data-ref="2">more</span>
  </div>
  <div class="column__4 col show">3
    <span class="more" data-ref="3">more</span>
  </div>
</div>

<div class="row">
  <div class="column__4 col show">4
    <span class="more" data-ref="4">more</span>
  </div>
  <div class="column__4 col show">5
    <span class="more" data-ref="5">more</span>
  </div>
  <div class="column__4 col show">6
    <span class="more" data-ref="6">more</span>
  </div>
</div>

<div class="row">
  <div class="column__4 col show">7
    <span class="more" data-ref="7">more</span>
  </div>
  <div class="column__4 col show">8
    <span class="more" data-ref="8">more</span>
  </div>
</div>

<div id="content">
  content is king
</div>

<script>
function placeAfter($block) {
    $block.after($('#content'));
}
var $chosen = null;

$(document).on('click', '.more', function(e){
//$(document).on('click', '.more', function(e){

    $chosen = $(this);
    var n = $chosen.closest('div.column__4').find('span').attr("data-ref");
    console.log(n);

    $('#content').css('display','block').text(n); //changed to display:block
    var top = $(this).offset().top;
    var $blocks = $(this).nextAll('.row'); //changed to .row
    if ($blocks.length == 0) {
        placeAfter($(this).closest(".row")); //changed to .row
        return false;
    }
    $blocks.each(function(i, j) {
        if($(this).offset().top != top) {
            placeAfter($(this).prev('.row')); //changed to .row
            return false;
        } else if ((i + 1) == $blocks.length) {
            placeAfter($(this));
            return false;
        }
    });

   e.preventDefault();
});

$(window).on('resize', function() {
    if ($chosen != null) {
        $('#content').css('display','none');
        $('body').append($('#content'));
        $chosen.trigger('click');
    }
});
</script>

</body>
</html>

1 Like

I know its not relevant now that things have changed but my demo in the other thread used flexbox also and I’ve just updated it to use only the one tab.

It has responsive columns although a lot of the logic should probably be moved to js :slight_smile:

1 Like

Thanks @Ray.H , been working endless on this, stressing out :upside_down:

What you suggest is a good approach if I know for certain the amount of containers. Unfortunately, this is a responsive setup and the rows will be a mixture of 1-10+ depending on the screen size and containers available.

And thanks @PaulOB l, nice improvement of the last codepen. Something I can look at moving forward for stuff related.

Ok, as mentioned. I’ve been working full steam ahead for the past 3 days and after chatting with a colleague come up with a solution :grin:

Similar approach as the last, with less code.

var $chosen = null;
var $allBlocks = [];
$(function(){
	$allBlocks = $('#results .column__4');
})

$(window).on('resize', function() {
    if ($chosen != null) {
        $('#content').css('display','none');
        $('body').append($('#content'));
        $chosen.trigger('click');   
    }
});

$('.read_more').on('click', function() {
    $chosen = $(this);
    var position = $chosen.parent('.column__4').position();
    $('#content').css('display','inline-block');
    $allBlocks.filter(function(idx, ele){
    	return $(ele).position().top == position.top;
    })
    .last()
    .after($('#content'));
});

Working example here - http://jsfiddle.net/qr3copqe/

Still not too sure how it fully works, I get the idea :nerd:
Hopefully this will be useful for everybody viewing this, I know it’s been a tricky challenge.

Cheers, Barry

2 Likes

It works mostly on the principle that .append and .after, if supplied a single target, and an existing DOM object, moves the element to the target position, rather than duplicate it. (Somewhat unintuitive to the name .append, I know)

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.