0

Is there an easy way (in pure javascript) to fold a div between a setted max-height and the height of its text?

In detail, I want to load a div with a preset height (40 pixels for example), and show a "show more" button, so when you click on it the div sets to the height of the text inside it (80px for example). And when you click again you set the div's height to its initial height (40 pixels).

A visual example would be something like this:

Initial state (40 pixels)

The text of the div
would be something like
this, so when the button

show more info...

if you click on "show more info" you get to this state (80 pixels)

The text of the div
would be something like
this, so when te button
is pressed..
it shows the remaining text
;)

show less info...

if you click on "show less info" you get to the previos state (40 pixels)

I've tried with height / max-height and clientHeight, but when you set the height property value you override the clientHeight one.

Thanks in advance. If the solution is too complex, don't hesitate to answer.

Packet Tracer
  • 3,884
  • 4
  • 26
  • 36

3 Answers3

1

You might want to take a look to this tutorial: http://papermashup.com/simple-jquery-showhide-div/

lomse
  • 4,045
  • 6
  • 47
  • 68
1

One possibly overly-complicated solution:

$('p').each(

function() {
    var that = $(this);
    that.attr('data-fullheight', that.height());
    that.height(that.height() / 2);
    that.closest('div').append('<a src="#" class="readmore">Read more</a>');
});

$('div').on('click', 'a.readmore', function(e) {
    var p = $(this)
        .closest('div')
        .find('p[data-fullheight]'),
        full = p.attr('data-fullheight');
    p.animate({
        'height' : full == p.height() ? full/2 : full
        },200)
});​

Which assumes the following HTML (albeit the div id isn't necessary):

<div id="text">
    <p>...text...</p>
</div>

JS Fiddle demo.

Just because I thought that last one wasn't over-complicated enough, I thought I'd post this (plain-JavaScript!) solution as well:

var readmores = [];

function heights(el) {
    if (!el) {
        return false;
    }
    else {
        var h = parseInt(window.getComputedStyle(el, null).height, 10),
            moreLess = document.createElement('a'),
            text = document.createTextNode('Read more'),
            parent = el.parentNode;

        readmores.push(moreLess);

        moreLess.src = '#';
        moreLess.className = 'readmore';
        moreLess.appendChild(text);

        parent.insertBefore(moreLess, el.nextSibling);

        el.setAttribute('data-fullheight', h);
        el.style.height = Math.floor(h / 2) + 'px';
    }
}

function toggleHeight(el) {
    if (!el) {
        return false;
    }
    else {
        var full = el.getAttribute('data-fullheight'),
            curHeight = parseInt(el.style.height, 10);

        el.style.height = full == curHeight ? Math.floor(full / 2) + 'px' : full + 'px';
    }
}

function toggleText(el) {
    if (!el) {
        return false;
    }
    else {
        var text = el.firstChild.nodeValue;
        el.firstChild.nodeValue = text == 'Read more' ? 'Read less' : 'Read more';
    }
}

var paras = document.getElementsByTagName('p');

for (var i = 0, len = paras.length; i < len; i++) {
    var cur = paras[i];
    heights(cur);
}

for (var i=0, len=readmores.length; i<len; i++){
    readmores[i].onclick = function(){
        toggleHeight(this.previousElementSibling);
        toggleText(this);
    }
}

JS Fiddle demo.

This works (in Chrome 21), but makes absolutely no allowance for IE for which it will need to be amended some.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
1

An easy solution to solve this is just using the max-height property.

You can set:

div.style.maxHeight = 40; //initial state

if the button is pressed:

div.style.maxHeight = 80; //final state (set a value bigger than the text is going to be)

if pressed again:

div.style.maxHeight = 40; //initial state again

The problem of this solution is that you don't really know the real text-size, so if you set a max-height smaller than the text size, it would'n work properly. But for me solves the issue.

Thanks, and hope this helps to somebody else.

Packet Tracer
  • 3,884
  • 4
  • 26
  • 36