foldable div between a max-height its original text height - javascript

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.

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

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.

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.

Related

how to change a part of paragraph's color [duplicate]

This question already has answers here:
Invert CSS font-color depending on background-color
(5 answers)
Closed 6 years ago.
i have a draggable div that is under a blue paragraph , i wanna change the part of paragraph color that is on div ... like the image below
and here is my codes:
<html>
<head>
<script>
$(document).ready(function(){
$("#div1").draggable();
});
</script>
<style>
#div1{
position : absolute ;
top : 10px ;
left : 20px ;
background : black ;
width : 200px ;
height : 200px ;
cursor : move ;
}
#p1{
position : absolute ;
top : 100px ;
left : 200px ;
color : blue ;
}
</style>
<head>
<body>
<div id="div1"></div>
<p id="p1">some text</p>
</body>
</html>
jsfiddle : https://jsfiddle.net/e7qvqot9/
Maybe do this:
You need to have 2 separate paraghraps, the first one is blue and is located inside the div, the second one is blue, and can be found outside the div.
Set the z-order, so the white text is on the top, then comes the div, and the the blue paragraph. The div also needs to have the overflow: hidden attribute.
This part is a bit finicky. Position the blue text somewhere, for example, ypu currently have ot at (100; 200). Then, set the white paragraph, so the divs position relatove to the top-left corner + the parapgraph's position relative to the div equals to the first paragraph's position. So, if you have the div at (10; 20), then you need to have the paragraph at (90; 180) relative to the div.
This works in most browsers, where z-ordering works. However, you can bypass that, by putting the elements in the rigjt place
Here, I made an example
https://goo.gl/PafOMJ
This is currently the shortest solution
What about this: Fiddle
This works exactly as you want, and is a pure JavaScript solution. Although it involves a lot of performance overhead, it should be okay for the small text mentioned in the question.
$(document).ready(function(){
var boxLeftX;
var boxLeftY;
$("#div1").draggable({
drag: function(){
var offset = $(this).offset();
boxLeftX = offset.left;
boxLeftY = offset.top;
}
});
var $source = $('#p1');
var characters = $source.html();
var sourceLength = characters.length;
var replacement = "";
for(var i = 0 ; i < sourceLength ; ++i){
replacement += "<span class='interesting'>" + characters[i] + "</span>";
}
$source.html(replacement);
var positionsStore = [];
var positionOfPara = $('#p1').position();
$('.interesting').each(function(index, element){
var tempObj = {};
var tempPos = $(element).position();
tempObj.x = Number(tempPos.left) + Number(positionOfPara.left);
tempObj.y = tempPos.top + positionOfPara.top;
tempObj.ele = element;
positionsStore.push(tempObj);
});
$('#div1').on("mouseup", function(evt){
$.each(positionsStore, function(index, item){
var boxX = $('#div1').position().left;
var boxY = $('#div1').position().top;
if(checkIfCoordIsInBox(item,boxX, boxY)){
$(item.ele).removeClass("blue").addClass("orange");
}else{
$(item.ele).removeClass("orange").addClass("blue");
}
})
});
});
function checkIfCoordIsInBox(charObj,x,y){
console.log(charObj.x);
console.log(charObj.y);
if(((charObj.x - x) <= 200) && ((charObj.y - y) <= 200)){
return true;
}
return false;
}

How to check bottom of child div touching parent bottom

i'm trying to change position of a child element(with varying height based on text) using range input,i would like to stop applying top position once the child div touches the bottom of the parent having fixed height.
$('#change_position').on('input', function () {
var val = +$(this).val(),
ScrSize = parseInt($('.screen').css('height')),
Stop = $('.screentip').offset().top,
h = parseInt($('.screentip').css('height')),
tofsset = Stop - h;
if (tofsset < ScrSize) {
$('.screentip').css('top', val + "%");
}
});
The height you are expecting jQuery to return is actually a string with the ending "px". You can use the function .height(). This will return you the height of the element as integer. I have tried a slightly modiefied version of your code:
$('#input').on('input', function () {
var val = parseInt($(this).val()),
ScrSize = parseInt($('#container').height()),
TxtSize = parseInt($("#text").height()),
Stop = ScrSize - TxtSize,
valInPixel = ScrSize * val / 100;
if (valInPixel < Stop) {
$('#text').css('top', val + "%");
}
else
{
$("#text").css("top", Stop + "px");
}
});
The else part will position your element to the bottom, if the number exceeds the frame. You may also have to be aware of padding and margin. This could also lead to mispositioning.
Hope this helps.

Opening Div at a specific position

I need to open a div at a specific location on the page. When I focus on a textbox the div should be opened(made visible). I am able to do this part. The problem is it opens right underneath the textbox and when there is no scroll on the page, it creates one. I need help in showing the div above the textbox when there is more space on upper half of the page then the lower half of the page. Here is the JSFiddle I have created and if someone can edit it, it would be of too much help to me.
And this is how I am opening the div:
function openDIV(activatorCtl) {
var leftpos = 0;
var toppos = 0;
var sScrollTop = getScrollTop;
var aTag = activatorCtl;
do {
aTag = aTag.offsetParent;
sScrollTop = (aTag.scrollTop > sScrollTop) ? aTag.scrollTop : sScrollTop;
leftpos += aTag.offsetLeft;
toppos += aTag.offsetTop;
} while (aTag.tagName != 'BODY');
document.getElementById("divDetails").style.left = leftpos + "px";
document.getElementById("divDetails").style.top = toppos + 20 + "px";
document.getElementById("divDetails").style.zIndex = "999";
document.getElementById("divDetails").style.visibility = "visible";
}
You mean like this?
https://jsfiddle.net/36vdoaqo/3/
I added an if for when the toppos is bigger than 250 (your divs height)
if(toppos <= 250)
Another tip:
You use this 4 times in a row:
document.getElementById("divDetails")
save this element in an variable to get shorter statements like:
var detailsDiv = document.getElementById("divDetails");
detailsDiv.style.left = leftpos + "px";
detailsDiv.style.zIndex = "999";
EDIT: i did not save the jsfiddle properly.

Font size auto adjust to fit

I'm trying to do what the title says. I've seen that font-size can be a percentage. So my guess was that font-size: 100%; would do it, but no.
Here is an example: http://jsfiddle.net/xVB3t/
Can I get some help please?
(If is necesary to do it programatically with js there is no problem)
This question might help you out but I warn you though this solves it through jQuery:
Auto-size dynamic text to fill fixed size container
Good luck.
The OP of that question made a plugin, here is the link to it (& download)
BTW I'm suggesting jQuery because as Gaby pointed out this can't be done though CSS only and you said you were willing to use js...
Can't be done with CSS.
100% is in relation to the computed font-size of the parent element.
reference: http://www.w3.org/TR/CSS2/fonts.html#font-size-props
For a jQuery solution look at Auto-size dynamic text to fill fixed size container
I was looking into this for work and I liked tnt-rox's answer, but I couldn't help but notice that it had some extra overhead that could be cut out.
document.body.setScaledFont = function(){
this.style.fontSize = (this.offsetWidth*0.35)+'%';
return this;
}
document.body.setScaledFont();
Cutting out the overhead makes it run a little bit quicker if you add it to an onresize event.
If you are only looking to have the font inside a specific element set to resize to fit, you could also do something like the following
window.onload = function(){
var scaledFont = function(el){
if(el.style !== undefined){
el.style.fontSize = (el.offsetWidth*0.35)+'%';
}
return el;
}
navs = document.querySelectorAll('.container>nav'),
i;
window.onresize = function(){
for(i in navs){
scaledFont(navs[i]);
}
};
window.onresize();
};
I just noticed nicolaas' answer also had some extra overhead. I've cleaned it up a bit. From a performance perspective, I'm not really a fan of using a while loop and slowly moving down the size until you find one that fits.
function setPageHeaderFontSize(selector) {
var $ = jQuery;
$(selector).each(function(i, el) {
var text = $(el).text();
if(text.length) {
var span = $("<span>").css({
visibility: 'hidden',
width: '100%',
position: 'absolute',
'line-height': '300px',
top: 0,
left: 0,
overflow: 'visible',
display: 'table-cell'
}).text(text),
height = 301,
fontSize = 200;
$(el).append(span);
while(height > 300 && fontSize > 10) {
height = span.css("font-size", fontSize).height();
fontSize--;
}
span.remove();
$(el).css("font-size", fontSize+"px");
}
});
}
setPageHeaderFontSize("#MyDiv");
And here is an example of my earlier code using jquery.
$(function(){
var scaledFont = function(el){
if(el.style !== undefined){
el.style.fontSize = (el.offsetWidth*0.35)+'%';
}
return el;
};
$(window).resize(function(){
$('.container>nav').each(scaledFont);
}).resize();
});
A bit late but this is how I approach this problem:
document.body.setScaledFont = function() {
var f = 0.35, s = this.offsetWidth, fs = s * f;
this.style.fontSize = fs + '%';
return this
}
document.body.setScaledFont();
The base document font is now set.
For the rest of your elements in the dom set font sizes as % or em and they will scale proportionately.
here I have a mootools solution:
Element.implement("fitText", function() {
var e = this.getParent();
var maxWidth = e.getSize().x;
var maxHeight = e.getSize().y;
console.log(maxWidth);
var sizeX = this.getSize().x;
var sizeY = this.getSize().y;
if (sizeY <= maxHeight && sizeX <= maxWidth)
return;
var fontSize = this.getStyle("font-size").toInt();
while( (sizeX > maxWidth || sizeY > maxHeight) && fontSize > 4 ) {
fontSize -= .5;
this.setStyle("font-size", fontSize + "px");
sizeX = this.getSize().x;
sizeY = this.getSize().y;
}
return this;
});
$$("span").fitText();
Here is another jQuery solution ...
/**
* Resizes page header font-size for the text to fit.
* basically we add a hidden span into the header,
* put the text into it and then keep reducing the super large font-size
* for as long as the height of the span exceeds the super
* tall line-height set for the test (indicating there is more than one line needed
* to show the text).
*/
function setPageHeaderFontSize(selectorString) {
jQuery(selectorString).each(
function(i, el) {
var text = jQuery(el).text();
var length = text.length;
if(length) {
var id = "TestToSeeLengthOfElement_" + i;
jQuery(el).append("<span style='visibility: hidden; width: 100%; position: absolute; line-height: 300px; top: 0; left: 0; overflow: visible; display: table-cell;' id='"+id+"'>"+text+"</span>");
var innerEl = jQuery("#"+id);
var height = 301;
var fontSize = 200;
while(height > 300 && fontSize > 10) {
height = jQuery(innerEl).css("font-size", fontSize).height();
fontSize--;
}
jQuery(innerEl).remove();
jQuery(el).css("font-size", fontSize+"px");
}
}
);
}
//you can run it like this... using any jQuery enabled selector string (e.g. h1.pageHeaders works fine).
setPageHeaderFontSize("#MyDiv");
Here's a way to find the height of the text that you are using.
It's simple and only uses javascript. You can use this to adjust your text relative to the height you want.
function getTextHeight(text, fontSize) {
var numberOfLines = 0;
var STL = text;
for(var i = 0; i < STL.length; i++){
if(STL[i] === '<'){
try{
if(STL[i + 1] === 'b' && STL[i + 2] === 'r' && STL[i + 3] === '>'){
numberOfLines++;
}
}
catch(err){
break;
}
}
return (numberOfLines + 1) * fontSize;
}

How to get top and left style property values in Javascript

I have a little bit of Javascript that almost works correctly. Here's the code:
function toggle(curlink) {
curlink.style.backgroundColor = curlink.style.backgroundColor == "yellow" ? "transparent" : "yellow";
var maindiv = document.getElementById("grid");
var links = maindiv.getElementsByTagName("a");
var list = "";
for (var i = 0; i < links.length; ++i) {
var link = links[i];
if (link.style.backgroundColor == "yellow") {
list += ("," + parseInt(link.style.left, 10) + "-" + parseInt(link.style.top, 10));
}
}
document.theForm.theList.value = list.substring(1);
return false;
};
window.onload = function() {
var links = document.getElementById("grid").getElementsByTagName("a");
for (var i = 0; i < links.length; ++i) {
links[i].onclick = function() { return toggle(this); }
}
};
The issue is with line #9; it only works when I specify values for the top and left style property of every link in the array. How do I get the top and left style property values (or X and Y coordinates) of each link in the array with Javascript when those values aren't given?
Also, what would the code above look like in jquery? Not that it's needed - I just want to reduce the code a little and dabble in the jquery framework (I'm a Javascript newbie).
Thanks in advance,
Dude-Dastic
link.offsetLeft and link.offsetTop. More about finding position here. They'll be positions relative to the offsetParent, but the link shows a way to get position relative to the document.
offsetParent will evaluate to the body if the parent elements are positioned statically or there's no table in the parent hierarchy. If you want a position other than body then update the parent of the links to have a non-static position, perhaps relative
I'm not familiar with JQuery so I can't help there
The jQuery might look something like this. Untested.
$(function(){
// Get all <a> descendents of #grid
var $anchors = $('#grid a');
// Bind a click handler to the anchors.
$anchors.click(function(){
var $clickedAnchor = $(this);
var coordinates = [];
// Set the background color of the anchor.
$clickedAnchor.css('background-color', $clickedAnchor.css('background-color') == 'yellow' ? 'transparent' : 'yellow');
// Loop through each anchor.
$anchors.each(function(){
var $anchor = $(this);
if ($anchor.css('background-color') == 'yellow') {
var offset = $anchor.offset();
coordinates.push(offset.left + '-' + offset.top);
// Or maybe..
// var parentOffset = $('#grid').offset();
// coordinates.push((offset.left - parentOffset.left) + '-' + (offset.top - parentOffset.top));
}
});
$('#theList').val(coordinates.join(','));
return false;
});
});

Categories

Resources